{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b34b6e23",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_154868/1800585390.py:16: DeprecationWarning: The environment `pettingzoo.mpe` has been moved to `mpe2` and will be removed in a future release.Please update your imports.\n",
      "  from pettingzoo.mpe import simple_adversary_v3\n"
     ]
    }
   ],
   "source": [
    "# Inline Plotting\n",
    "%matplotlib inline\n",
    "\n",
    "# Import libraries\n",
    "import random\n",
    "from collections import namedtuple, deque\n",
    "\n",
    "import matplotlib\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from matplotlib import pyplot as plt\n",
    "from pettingzoo.mpe import simple_adversary_v3\n",
    "from psutil import virtual_memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "16c406f8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<contextlib.ExitStack at 0x7efcc7d62150>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Set up matplotlib\n",
    "is_ipython = 'inline' in matplotlib.get_backend()\n",
    "if is_ipython:\n",
    "    from IPython import display\n",
    "\n",
    "plt.ion()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75f9cff0",
   "metadata": {},
   "source": [
    "1. 经验回放缓冲区（Replay Buffer）\n",
    "经验回放缓冲区是强化学习中使用的数据存储与检索方法。其原理是将智能体在环境中的经验存储于缓冲区，训练时从缓冲区随机抽取部分数据用于学习。这带来两点优势：其一，提高数据利用率，避免经验仅使用一次即被丢弃；其二，打破数据的时间相关性，降低训练的不稳定性。我们选择使用固定大小的循环队列实现该缓冲区，当队列满时自动丢弃最早的经验数据。\n",
    "为此，我们需要实现两个类：\n",
    "- Transition：一个具名元组，代表环境中的单次状态转移。它本质上是将（状态，动作）对映射到其（下一状态，奖励）结果，其中状态为后文所述的屏幕差分图像。\n",
    "- ReplayBuffer：一种有界大小的循环缓冲区，用于存储近期观察到的状态转移。它还实现了 .sample() 方法，用于选择随机批量的状态转移数据以进行训练。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ce9b3483",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"Transition is a namedtuple used to store a transition.\n",
    "\n",
    "The structure of Transition looks like this:\n",
    "    (state, action, reward, next_state, done)\n",
    "\"\"\"\n",
    "Transition = namedtuple('Transition', ('state', 'action', 'reward', 'next_state', 'done'))\n",
    "\n",
    "class ReplayBuffer:\n",
    "    \"\"\"ReplayBuffer is a class used to achieve experience replay.\n",
    "\n",
    "    It's a buffer composed of a deque with a certain capacity. When the deque is full, it will automatically remove the oldest transition in the buffer.\n",
    "\n",
    "    Attributes:\n",
    "        _storage: The buffer to store the transitions.\n",
    "\n",
    "    Examples:\n",
    "        A replay buffer structure looks like below:\n",
    "        [\n",
    "            (state_1, action_1, reward_1, next_state_1, done_1),\n",
    "            (state_2, action_2, reward_2, next_state_2, done_2),\n",
    "            ...\n",
    "            (state_n, action_n, reward_n, next_state_n, done_n),\n",
    "        ]\n",
    "        Each tuple is a transition.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, capacity=100_000):\n",
    "        \"\"\"Initial a replay buffer with capacity.\n",
    "\n",
    "        Args:\n",
    "            capacity: Max length of the buffer.\n",
    "        \"\"\"\n",
    "        self._storage = deque([], maxlen=capacity)\n",
    "\n",
    "    def add(self, state, action, reward, next_state, done):\n",
    "        \"\"\"Add a transition to the buffer.\n",
    "\n",
    "        Args:\n",
    "            state:          The state of the agents.\n",
    "            action:         The action of the agents.\n",
    "            reward:         The reward of the agents.\n",
    "            next_state:     The next state of the agents.\n",
    "            done:           The termination of the agents.\n",
    "\n",
    "        Returns: None\n",
    "\n",
    "        \"\"\"\n",
    "        transition = Transition(state, action, reward, next_state, done)\n",
    "        self._storage.append(transition)\n",
    "\n",
    "    def sample(self, batch_size):\n",
    "        \"\"\"Sample a batch of transitions from the buffer.\n",
    "\n",
    "        Args:\n",
    "            batch_size: The number of transitions that we want to sample from the buffer.\n",
    "\n",
    "        Returns: A batch of transitions.\n",
    "\n",
    "        Example:\n",
    "            Assuming that batch_size=3, we'll randomly sample 3 transitions from the buffer:\n",
    "                state_batch = (state_1, state_2, state_3)\n",
    "                action_batch = (action_1, action_2, action_3)\n",
    "                reward_batch = (reward_1, reward_2, reward_3)\n",
    "                next_state_batch = (next_state_1, next_state_2, next_state_3)\n",
    "                done_batch = (done_1, done_2, done_3)\n",
    "        \"\"\"\n",
    "        transitions = random.sample(self._storage, batch_size)\n",
    "        state_batch, action_batch, reward_batch, next_state_batch, done_batch = zip(*transitions)\n",
    "        return state_batch, action_batch, reward_batch, next_state_batch, done_batch\n",
    "\n",
    "    def __len__(self):\n",
    "        \"\"\"Return the length of the buffer.\"\"\"\n",
    "        return len(self._storage)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bee8b94",
   "metadata": {},
   "source": [
    "2. 简单神经网络\n",
    "\n",
    "此代码是用 PyTorch 框架编写的简单神经网络类，具有以下特性：\n",
    "- 继承关系：继承自nn.Module类，这是 PyTorch 中所有神经网络模型的基类。\n",
    "- 网络结构：定义了三个全连接层（nn.Linear），即输入层、隐藏层和输出层。其参数为输入维度、输出维度和隐藏维度。\n",
    "- 前向传播过程：在forward方法中定义了神经网络的前向传播：首先将输入数据通过第一层并应用 ReLU 激活函数（F.relu），然后将结果再次通过第二层并应用 ReLU 激活函数，最后将结果通过第三层并返回输出数据。\n",
    "\n",
    "采用三层神经网络的理由如下：\n",
    "- 每个线性层引入额外参数和非线性激活函数，增加了模型的复杂度和灵活性。更多的线性层意味着模型能够学习更丰富的特征表示，更好地拟合输入与输出之间的复杂关系。\n",
    "- 若模型过于复杂而训练数据量相对较小，易出现过拟合问题。过多的线性层会增加模型复杂度，使其更易记住训练样本的细节，而忽略对新数据的泛化能力。\n",
    "- DQN 基于 Q 学习算法，通常采用三层 CNN 结构。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "49d5151a",
   "metadata": {},
   "outputs": [],
   "source": [
    "class SimpleNet(nn.Module):\n",
    "    \"\"\"SimpleNet is a 3-layer simple neural network.\n",
    "\n",
    "    It's used to approximate the policy functions and the value functions.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, input_dim, output_dim, hidden_dim):\n",
    "        \"\"\"Initial a simple network for an actor or a critic.\n",
    "\n",
    "        Args:\n",
    "            input_dim: The input dimension of the network.\n",
    "            output_dim: The output dimension of the network.\n",
    "            hidden_dim: The hidden layer dimension of the network.\n",
    "        \"\"\"\n",
    "        super(SimpleNet, self).__init__()\n",
    "        self.layer1 = nn.Linear(input_dim, hidden_dim)\n",
    "        self.layer2 = nn.Linear(hidden_dim, hidden_dim)\n",
    "        self.layer3 = nn.Linear(hidden_dim, output_dim)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.layer1(x))\n",
    "        x = F.relu(self.layer2(x))\n",
    "        return self.layer3(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "875e15ce",
   "metadata": {},
   "source": [
    "3. Gumbel Softmax 技巧\n",
    "\n",
    "在多智能体强化学习（MPE）环境中，每个智能体的动作空间是离散的。而我们使用的 DDPG（深度确定性策略梯度）算法要求智能体的动作对策略参数是可导的，这在连续动作空间中自然成立，但在离散动作空间中不成立。然而，这并不意味着无法使用 MADDPG（多智能体 DDPG）算法解决当前任务，因为我们可以使用一种称为 Gumbel-Softmax 的方法来获取离散分布的近似可导样本。以下简要介绍其原理并提供实现代码。\n",
    "\n",
    "假设你有一个服从离散分布 $ K = (a_1, \\dots, a_k) $的随机变量。其中 $ a_i \\in [0, 1] $ 表示 $ P(Z = i)$ ，且 $ \\sum_{i = 1}^k a_i = 1 $ 。如果我们想要根据这个分布$ z \\sim K $进行采样，会发现对这个离散分布进行采样是不可导的。\n",
    "\n",
    "那么，有没有办法让离散采样变得可控制呢？答案是通过 heavy parameterisation（重型参数化，也可译为重参数化 ），我们会用到gumbel-softmax 技术。具体来说，我们引入一个重型参数因子 $ g_i $，它是从 $ \\text{Gumbel}(0, 1) $ 分布中采样得到的噪声：\n",
    "\n",
    "$ g_i = -\\log(-\\log u), u \\sim \\text{Uniform}(0, 1) $\n",
    "\n",
    "Gumbel-softmax 采样可表示为：\n",
    "\n",
    "$ y_i = \\frac{\\exp((\\log a_i + g_i)/\\tau)}{\\sum_{j = 1}^k \\exp((\\log a_j + g_i)/\\tau)}, i = 1, \\dots, k $\n",
    "\n",
    "在这种情况下，如果通过 $ z = \\arg\\max_i y_i $ 计算离散值，该离散值近似等同于从离散分布 $ z \\sim K $ 中采样得到的值。此外，对 a 的梯度自然会被引入到采样结果中。$ \\tau > 0 $ 被称为分布的温度参数，通过调整它，可以控制生成的 Gumbel-softmax 分布与离散分布的相似程度：$ \\tau $ 越小，得到的分布越趋近于 $ \\text{onehot}(\\arg\\max_i (\\log a_i + g_i)) $ 的结果；$ \\tau $ 越大，得到的分布越趋近于均匀分布。\n",
    "接下来，定义一些需要用到的工具函数，包括与Gumbel-softmax 采样相关的函数，这使得 DDPG 能够应用于离散动作空间.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "09f3e6f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.return_types.max(\n",
      "values=tensor([[0.6965]]),\n",
      "indices=tensor([[3]]))\n",
      "tensor([[False, False, False,  True, False]])\n",
      "torch.Size([1, 5])\n"
     ]
    }
   ],
   "source": [
    "l = torch.tensor([[0.0936, 0.0518, 0.0395, 0.6965, 0.1185]])\n",
    "l_max = l.max(1, keepdim=True)\n",
    "print(l_max)\n",
    "print(l == l.max(1, keepdim=True)[0])\n",
    "print(l.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dda944f8",
   "metadata": {},
   "source": [
    "1. Gumbel-Softmax 分布\n",
    "\n",
    "对于给定的 logits 向量 $ z = [z_1, z_2, ..., z_K] $，Gumbel-Softmax 采样过程如下：\n",
    "- 从标准 Gumbel 分布中采样噪声：\n",
    "$ g_i \\sim \\text{Gumbel}(0, 1), \\quad g_i = -\\log(-\\log(u_i)), \\quad u_i \\sim \\text{Uniform}(0, 1)$ \n",
    "- 将噪声添加到 logits 上并应用 softmax：\n",
    "$ y_i = \\frac{\\exp((z_i + g_i)/\\tau)}{\\sum_{j=1}^K \\exp((z_j + g_j)/\\tau)}$ \n",
    "\n",
    "其中 $ \\tau$  是温度参数，控制分布的平滑程度：\n",
    "- 当 $ \\tau \\to 0$  时，$ y_i$  趋近于 one-hot 向量（离散化）\n",
    "- 当 $ \\tau \\to \\infty$  时，$ y_i$  趋近于均匀分布（完全平滑）\n",
    "\n",
    "2. 直通估计器的数学原理直通估计器的目标是在保持离散输出的同时，让梯度通过连续的近似分布传递。数学上，可以表示为：\n",
    "\n",
    "$ \\hat{y} = y_{hard} - y_{soft} + y_{soft}$ \n",
    "\n",
    "其中：\n",
    "- $ y_{soft}$  是 Gumbel-Softmax 采样得到的连续分布\n",
    "- $ y_{hard}$  是离散化后的 one-hot 向量\n",
    "\n",
    "前向传播：\n",
    "\n",
    "$ \\hat{y}$  的值等于 $ y_{hard}$ ，因此可以作为离散动作与环境交互。\n",
    "\n",
    "反向传播：\n",
    "\n",
    "由于 (y_hard - y).detach() 的存在，梯度不会通过 $ y_{hard}$  传递，而是直接通过 $ y_{soft}$  传递。从数学上看：\n",
    "\n",
    "$ \\frac{\\partial \\hat{y}}{\\partial z} = \\frac{\\partial y_{soft}}{\\partial z}$ \n",
    "\n",
    "这使得整个过程在保持离散输出的同时，允许梯度正确地反向传播到 logits。\n",
    "\n",
    "3. 为什么这样可以工作？\n",
    "\n",
    "Gumbel-Softmax 技巧的核心在于：\n",
    "- 重参数化：将离散采样过程转化为对噪声的确定性变换，使得可以计算梯度。\n",
    "- 温度退火：通过调整温度参数 $ \\tau$ ，可以在训练时使用较大的 $ \\tau$  保证平滑性，在推理时使用较小的 $ \\tau$  接近离散动作。\n",
    "- 直通估计器：通过巧妙的梯度路由，解决了离散化操作的不可微问题。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c4d7de9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def trans2onehot(logits, eps=0.01):\n",
    "    \"\"\"Transform the output of the actor network to a one-hot vector.\n",
    "\n",
    "    Args:\n",
    "        logits:     The output value of the actor network.\n",
    "        eps:        The epsilon parameter in the epsilon-greedy algorithm used to choose an action.\n",
    "\n",
    "    Returns: An action in one-hot vector form.\n",
    "\n",
    "    \"\"\"\n",
    "    '''\n",
    "    trans2onehot函数\n",
    "    功能：使用 epsilon-greedy 策略将 logits 转换为 one-hot 动作向量。\n",
    "    详细解释：\n",
    "        best_action 计算：找出每行 logits 中的最大值，生成对应的 one-hot 向量（最大值位置为 1，其余为 0）。\n",
    "        random_actions 生成：随机选择动作索引并转换为 one-hot 向量。\n",
    "        epsilon-greedy 选择：以概率eps选择随机动作，以概率1-eps选择最优动作。\n",
    "    '''\n",
    "    # Generates a one-hot vector form of the action selected by the actor network.\n",
    "    best_action = (logits == logits.max(1, keepdim=True)[0]).float()\n",
    "    '''\n",
    "    logits \n",
    "        tensor([[0.0936, 0.0518, 0.0395, 0.6965, 0.1185]], grad_fn=<SoftmaxBackward0>)\n",
    "    best_action \n",
    "        tensor([[0., 0., 0., 1., 0.]])\n",
    "    '''\n",
    "    # Generate a one-hot vector form of a random action.\n",
    "    size, num_actions = logits.shape\n",
    "    '''logits.shape torch.Size([1, 5])'''\n",
    "\n",
    "    random_index = np.random.choice(range(num_actions), size=size)\n",
    "    '''random_index [3]'''\n",
    "\n",
    "    random_actions = torch.eye(num_actions)[[random_index]].to(logits.device)\n",
    "    '''random_actions tensor([[0., 0., 0., 1., 0.]])'''\n",
    "\n",
    "    # Select an action using the epsilon-greedy algorithm.\n",
    "    random_mask = torch.rand(size, device=logits.device) <= eps\n",
    "    '''random_mask tensor([False])'''\n",
    "\n",
    "    selected_action = torch.where(random_mask.view(-1, 1), random_actions, best_action)\n",
    "    '''\n",
    "    select_action tensor([[0., 0., 1., 0., 0.]])\n",
    "    torch.where 是 PyTorch 库中的一个函数。它的作用是根据给定的条件，从两个张量中选择相应的元素来构建新的张量。\n",
    "    具体来说，如果条件张量中某个位置的元素为 True，就从第一个张量random_actions对应位置取元素；如果为 False，\n",
    "    就从第二个张量 best_action对应位置取元素。\n",
    "    '''\n",
    "    return selected_action\n",
    "\n",
    "\n",
    "def sample_gumbel(shape, eps=1e-20, tensor_type=torch.float32):\n",
    "    \"\"\"Sample a Gumbel noise from the Gumbel(0,1) distribution.\"\"\"\n",
    "    '''\n",
    "    sample_gumbel 函数\n",
    "    功能：从 Gumbel (0,1) 分布中采样噪声。\n",
    "    详细解释：\n",
    "        采样过程：通过对均匀分布采样进行两次对数变换实现 Gumbel 分布采样。\n",
    "        数值稳定性：添加eps防止对数运算中的数值溢出。\n",
    "    '''\n",
    "    U = torch.rand(shape, dtype=tensor_type, requires_grad=False)\n",
    "    gumbel_noise = -torch.log(-torch.log(U + eps) + eps)\n",
    "    return gumbel_noise\n",
    "\n",
    "\n",
    "def gumbel_softmax_sample(logits, temperature):\n",
    "    \"\"\"Sample from the Gumbel-Softmax distribution.\"\"\"\n",
    "    '''\n",
    "    gumbel_softmax_sample 函数\n",
    "    功能：实现 Gumbel-Softmax 的采样过程。\n",
    "    详细解释：\n",
    "    添加噪声：将 Gumbel 噪声添加到 logits 上。\n",
    "    温度缩放：通过温度参数temperature控制分布的平滑程度。\n",
    "    softmax：应用 softmax 将结果转换为概率分布。\n",
    "    '''\n",
    "    gumbel_noise = sample_gumbel(logits.shape, tensor_type=logits.dtype).to(logits.device)\n",
    "    y = logits + gumbel_noise\n",
    "    return F.softmax(y / temperature, dim=1)\n",
    "\n",
    "\n",
    "def gumbel_softmax(logits, temperature=1.0):\n",
    "    \"\"\"Sample from Gumbel-Softmax distribution and discretize it.\n",
    "    By returning a one-hot vector of y_hard, but with a gradient of y, we can get both a discrete action interacting with the environment and a correct inverse gradient.\n",
    "    从 Gumbel-Softmax 分布中采样并离散它\n",
    "    通过返回一个 y_hard 的单热向量，但梯度为 y，我们可以得到一个与环境交互的离散动作和一个正确的逆梯度\n",
    "    \"\"\"\n",
    "    '''\n",
    "    gumbel_softmax 函数\n",
    "    功能：实现 Gumbel-Softmax 技巧，生成可微分的离散动作。\n",
    "    详细解释：\n",
    "    采样：从 Gumbel-Softmax 分布中采样得到连续概率分布y。\n",
    "    离散化：使用trans2onehot将连续分布转换为 one-hot 向量y_hard。\n",
    "    直通估计器 (Straight-Through Estimator)：通过(y_hard - y).detach() + y实现离散动作的梯度回传，使得梯度能够通过连续分布y传递。\n",
    "    '''\n",
    "    y = gumbel_softmax_sample(logits, temperature)\n",
    "    y_hard = trans2onehot(y)\n",
    "    y = (y_hard.to(logits.device) - y).detach() + y\n",
    "    return y"
   ]
  },
  {
   "attachments": {
    "image-2.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOwAAAAeCAIAAACg62VRAAAFmElEQVR4Ae1avWvjSBTff+X9E1MaN+EKu7I6gQvBFYaFExiCOQjmGhEIJkUQASMMS5pFBAI2LLgwuFhwE+QiKMXiFEYpAi4CKgIqFuaY8Ye+FY89ku27MYFoZqT38Zuf3rx5oy9Y/AQCJ47AlxO3X5gvEMCCxIIEJ4+AIPHJT6FwQJD4iDnwOtb+MizvCC30rJ6qjZwjsUyQ+EgmImbGa19Fkj5NorDr2K9J/TEZOXZ8WHoNqYOj4LEgcY4TvYdox1RA6tkRCZ7rWAO9UQa4sSJDB2g+GxJIxvMBNEdUChJHAOHfdOezxW82sYtBA5A2+Qg89dZvAJRqsiJXAY6DxNibXCJQzINH46JIPB8bXSPlz7TcwGz91y4X/a+gT1m88iy9AtVuNAwvRRB+HwuJMX42qoA6kz1yGx7EKIrELJOYeu+TIV+OT43wzCT2Jh0ESH9KhuG4SIxtowLoah8WJ7vJ1HtKJLa7VeX+4GsXE7wYY2YSWzcIQEvjxZGR2JtcAiD9sBn6ziT27G+qVDsrITlQapmZ53KjZ5PV5W3YKgOS75IXRVYmYIzfx+1ye/y+w5PRR9ynu1atRBbl6A+1hguM+brGSmLHrAM0+mkva1Ekdu1vLakcBYi0lyCtQXUeGgCyOV+3OaO3EZt1sSOJFz/U0sXQxZZOvNJXTJ3qCACu6WtJtq5AZuMtS/3WY06/WeJS0PGmugQl5aJjdA39bxmQovnJet/+wLxdYyUxhfQiNWsqhMSedSNBWWlfG0ZXb8mA/tT8/cwDDVLrmXNHbQA/6eeN3lpN5v/dSGwbFYW8fCSvB/TPCnG7RzbO7dEqa3XulYxlMdOq8KA7M8/P5FseVX8SzlXzZbURsbtViNKFu2uMJKZViIwKWgEkdkftUtOcrWojJOvdzGl4YmhrSuJYY7CgDe7oJSiMd+1GYs91PYy9yRUCqK4rhXQdDIbeqQ5f+0vn4oq37HEeWmckvJekuiwz/HVC9Slfmef6dSsyPfL3yLq9n2svphoz8gyR0ljU+OuUpJcTiWf3alRjzDC5rpovPjT+led6m5ogiVPBbMG/a3UVIvF+6MVkb9mxG4mpcLqLhoqxyiXcMVlX6n7V0PkuxyiypVWh29xf/XZNanM/5KTLSOcxpGvV4Ona6UXiICJ0de1k7dtCJKaP8kQvaEvq9R4kphlwdX2q5P3UAGDTxNgx65sgnap+2wFyyJlyBrutiOh9dHpUspGL/3i6xkhib0JwXO4r4oZhXEA6EVBLFitoJoO0uu2xAwDaz0CpmCd6AVvSL3cn8RLNdTK0AnfTJOky37OcualUdB558RIMmvxslpEwQFxdYyQxtsnuOD0NK5TEc1MOBaYwTLRF7QlVtbmil6Ax3rU7ifGvOwkAXdLcjkRKUoyo3tLkYhk4nwJvZ1wzcw9JwbN2GEwC56YCAEvj4w/ydI2VxO74IlDwidnm3NMTu6tJbIR/B92ah6NsTIl9iwDaoWIKT/Ri+pI69iAxxu6j0aqVSjVZqinaaDYbaMofiDZV45H/yRrJWKLFhCSftuhb/FADe+qEB/i5xkpiTKkTK00uN3wkUIR+bAfaCY5mdC2GzU+LpMS7+OcT/NDLMM8f2ovEvpiTu/pwrKnD/z1LwIGZxJiuEq1hIdYlGOx3ea+WNc80433YAjj4Mer/lcT+TOV95TmjvsV20OgOzwHOj4DFn2HjDluA+ByjfqYqa1yQOAudg42RYMyvtpOXG6R2oUQL7Xkpy5ArSJwBziGHyDcJfMs7vL2xexJqpn7jwVtbljxB4ix0DjpGPmCQbvgVFbk6Qz5BqemWf/zJVTqjMEFiRsCKvX15jFuszq20EcM2R9NbPZHjTYLEOYIrRBeDgCBxMTgLLTkiIEicI7hCdDEICBIXg7PQkiMC/wL52yUiArEwgwAAAABJRU5ErkJggg=="
    },
    "image-3.png": {
     "image/png": "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"
    },
    "image.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAAb8AAAAzCAIAAACIdJEyAAAU5ElEQVR4Ae1dv2vbzBv//iv3T2g0WUyGerI2QQZBBkOghkAQgSAKLyJQTIYgCkEUinmhiEJBgYKHgoaAlxd3CMoQ0iEoQ8BDQUNAQ+G+PM/p9PMk27GcJumF0sjy6XT3uec+9/y6y/+o/JEISAQkAhKB1RH43+qPyCckAhIBiYBEgEr2lEIgEZAISAQeg4Bkz8egJp+RCEgEJAKSPaUMPAKBubdH8j/2j0dUIh+RCDxXBO69QV6+iT0TtVSypwgVeW8BAsCeg/P5glLya4nAK0Dgh00ke76CcXw2XZDs+WyGQjZk0whI9tw0wn9Z/ZI9/7IB/5u7K9nzbx79DfRdsucGQJVVPk8EJHs+z3F5sa2S7Plih042fFUEJHuuipgs34iAZM9GeOSXrwkByZ6vaTSfQV8kez6DQZBNeBoEXid7PgTjA3Ny3wKE8Q9neOyHLdT0l1TxAtlzeWm5n5gH4+DhWQ9l5JsKMX3WyLuJuWN4d+IGh9+t4cdZLP6yvbuNoEVT2/z6YqdXG+wZunohf7T5Q+909QG7tJVypcrov5oBfpjZfWV43taQxLNTVdn32qquptFwO/xqaFpXIR11R9N21A5Rupqm7Wh4kxDSUfsdsj953rmUIvaMp6PK+JXHM/f5SdNFV5SW8Hyo9O1ZiUCfpIPRrT8+Gmh9VdvRukpHPbAn11FFnOLpMSF9J8Avws8aUUy/WopScUcq1bVyo+Fd8/MBORXmm7fy5g1X0gZ70vjCYrND2cbZDpNf9K/fIUR3bx/dpZCl+Wv/3tRXEU+PFeVIKDD1Dy34JnD6RP3IBHJB0bW/Dr3BwLundD4Z7rgZZf8KvHeq2lfJnvfy2JPS8HOywHb6IsFIpWVbIcpounF1KB2lR0hL5B8JBGyzHYxu3IMOUTTr/CZhwt9z/71KiDL8fFNEK7AV0jueYrH5ZJ+IBebW1YnqXKU4bPpCDBqlVLInqE1M/VTeN0h+PH2vNBZYNITx1AINpdcw6vEPu7cWQYvbgMvDOrwvrlZ0d+7tIXvee4MyUYbeviKeDKKK/tA9ke5JKX2YsgVW/5KtCJUWghQ1Fqg8sd6NR0oLUE+F4zfXwTvP2CKkb/plA5xNOtW+zPHnrasRYkyQPHG+9M6qqz6MkXLcMFXXg1X4tBA0yZ4Mq+i7iepnPcUAfPXfChEv3Uzsd6t+2EEsyAGTndLDa34MnDdkLepf9v0i9oznAdpo8YX1UtmT0uCjCmtfhXZSYMD8VaxpyShOv27/4tHSEk0OwIgqrQMb6eCdN4R5JZ44oLgRQnKW1vzbkBB1fI1gwXzpWdNg+m/BcY9rRpMK0j7SUKMYNKl7MrTBvIXZIVY/49lpb83lDpw4RVkpDzMQNBl+24hpG3zsNcz8ckse/1nEnndcD30IZwJX1+NftoEna3RPSukvCGcAE4jVT3hQ/1xipA00MK1yDWmJvpsCRmu/gyE7cqUWFvC7EUJG3HGITs+EauPZSY+QgXfh6gVfOZiARLGrGmkKzIYuhKBJ9kzQjiYGjiUanqURgINJ1vSzoBOHEK1+guFSrK3hVy01uvAR9D6ibP7EIAF7ArBlK77Qtuf0oZ49KQ3OeiAhb+xq3BAUIsX0fz1dV9aSFjSQq9GtdjuILSSkQR9P2DOdcWghbXU6u9bo0LC/OMaW0ukPx1c5057OIAL7xGY7G1URaJI9U4mHwQPHZCWqHpz11o3kJE5Pxb5MX1e6YAtvug5n30aXYwMCVuKfwZIJE3cQsmrg7ux9a12V2TO+RdvtVbAn/cUX2PIhTGDWrRyXiwNHU5SDXBLCvW/taWbuRv1Q1EoLeyS69qw9DX52NG3XqvgcZyMi4qA2O8hnk8BxmXQLV3QCCiZLzhPRU1I0/cXK1Ml8dOMdD5Jea7r1fWlT4Pd8+snU+6qmdbt74+nUcz75YZ60oQEC0CR7piNDxeoniFS94vk7nBzrw0ND3WpUPa4c1FsWOT3fJLkaaZviH7ZKOoNjxzkzdaLo/7AL1ThxnDPHOXNnOX0nuhwPdw1jt6N9qlg2kW8S0pRd8dMdprHj5ou3bn3SQI49la4GpN+1/nUqEaS0fy1fhBe2kW/8rpPoiXf+6HDkfhnpTY2HIGrzCXVi7ezKaVI8o2D8VjcO9Y42LozKD8xjO+FmK0T2wbdTVQlFwwrtJBVpYWjGl7ZKeqP/YPbHl46mVMcdqU20pD2mg8IxTAS+ydwBbxI4yxIzXGgal+tGddX8LkpiigO7T3onOOC4MtUdv1au82Fmawrp2zOsNfzKDsCsZkoJQJPsmQdTsGCCPNVGciCOrL7zQ4q6QH3mV+L0LHhw8u+FlQ2cQCWB/uWbW7rDLBdYdZF8QYsUnGkKPKtgYSjJ1/PsJaL6s2/busqxJ/Qljq5ciBuU+tXW20r1XI2Ns9n8YtQ59SdHeR9I6A5YPGdmkwb1fzF7pupnEheGBoDiKQoNY+MwH1P/GMQ0dHcKzMi4I0cESIgk32yooWZYm0Yz+KAQ0mNWTnzpDHaMovGbdFNMLlz9XLaDpSHgHzkHLVIXciowNLtvB2WNj9eIv5k3QOyAwqhs7wOuUHHg7GnGv82VsZoxFSSvHl053epMhLJsgApTT7KnYHgga4LpdCBMtQG++behogzZXojZKSH9cY1SFvlHsMo2Gs7C+RBHPIYbftFZqjks0VUywoVXZT4HPD7a9EtiKKy/0Pc2PpTYE6qEfKlqg9t4magOiCpYF1NbydaPeDpKzOpbV68PmmNtC3RPSiF+CGOZ6n2gZHFpKTcoDj6ooNTAIOLce5eOCpBpZrQCCaNxoBQmJ60d1qbRBFHBH2VbM04nPMcy3zgBEfCvV+ogf6jyG6YDISSf81sqk9D0gvEoPdTEnhhGg5cqXU2cil+qDD4myTa5DAT2ip4gP1oA2nNgzziKSlM96+fvjECym+lVK9nyaW1wEc9s5v1Efw2kcdQpnliS+0MxKJTOKEqhS795xYudnjW6J6+AUlCKGfmCzlIhIxxy7l7ARTin1LBamuZb9p51rwTsSee+9Y/PMwkah3Pdt1PUDU0/mtk5JW52qhpHBngAt3vWhcjoy967kD0p5X/bALUzyKOuVTyxJPeHQh54lp3DKsmTCzPki/GQ+mFtHM2HG+9YzzzlfOtO1kuRGpV9u3wHs2fKVwl7VgQ1Lcfy85Umaywtm10wahPrnjS+Obf0LWRt+I9Ph+zp6lU1lssUHaHD4TmyZ/jN0MH2rfsJvf1u1QeRlG6fPSlNlm7F9K99U+nZP8TMzra3cQMH50bCs3FwBr6mLKVusdMTM/Z3QBcRAwE1MBUYXQTlYph4zLkbk+aq+rLA512AvHW/p2jmgGc55+krNKCND2AwwnthseG5X4HzJonFhV8HNRlp6buXYE+KSTMENxReOarASZLUhoLEB2I+GZLMwGcBE4WZmVg8M+R/p8pEw7Ci6loWA6ho/sPzeMAjvvNHkIeXqeG8n7jtLc/d/Av8vWwHofCvmfNWGx5bg/7APDJstksItu2i91DUQnjqfgL+HG63FV7e+IHhJtjlPJ95537IDLWHEDcyFfwkNbXiIpR35iSKDjocHnIKEDwvAO0P6563rt63prnIh6CbkIgmzrelm2BPyrf9drY6VS0vbR96l0iydQ/2d6fBemRSQrhaCtvpYCn80OyFYctg0XBLXoaZuolNxxbAojsJZyYYLBgwUWH5rUwYVCjy0zXtSKsXIt0zfQHmTheSBKJgfDAwT0bGru6yHOm0cN3F75kDG6VzvtRbb6B0bAySCB669wY8Hxu8zwuUnWXYk9LESFQ6W0o1Q4O3gQ0o3+yPWRNpRGh2CiKRfqT0ZgyGPDg9w89aYjY2DWuNtFyPMad/mMbtZyc5JwNvWeJkb4BiqQ5SCl5dop+BYLOUuEzNSRRY5tOIZmdDDX6MyR2lDzfuvkKUoftTrJdkzaxeoV2Vw42VuBljsjZfLyn9b1Tc1BdOPznOFxYWylda9p8km7ZBYALnTWkSIdUWQfuj7Am0oH+ucRbmegmRGz4FcrfpZtgzVT9JreKZLEQ89Q8Nip6VLLxIdm9dlvEQfsVVdolzOlD7yOQ+6ycTZW7ToU1U9BaBrKRTERPicn6cpB6xOZ+9pKUrvs/9Hva7Z3p0PJ+eDbqaMdwhOcUhjbeA9KufEjkIfcfc07QDyysk+lF67Zrs8BRUENLyIBzKsO5IKnATJ9G80NWVikOj1O/l2DNVP6urVFYfKvtcAUe6TFUAHpxkAWIaTWHTN+aN/w6cN7xY47CKpQXYs5seMRNdjwdE1GWmCAtce2nrufrZ1EGWAJtQDE6BAt2E3y1NIcq+652qydkOt66mG4bW0f7xRN5YCkeCFY9NYlEvLz1cAr3DFSUA5KebTrHoZryX6i7QI4zmA77V0Wf2AYuwRdcY4WSpKVdOrzSJRKD9SfYEWuCiko6b8AIs18LQJKU2onuC9xOP1eGiL2oSLETKO3acB9JlPlwYBe6R3t3WtO1OVzNsoeO+Uim+U+BwQSU3o0sU08KOF7zD97cBUkq2CPO3YJnlsOaPrPr75vNAfMZSkqwKWlg3F8yhFJV0Rbc+edPrOXMTx9OR9g6n1twfFc+aiiZG4icBFyFf2HCDdhIuE7V4dtLT9KE9mTiHQ2uS8bmobBLbqag2orK4pNUrnol7lFM80GXm48PcW9LXdRAPTdN06/xmfjkebnc6W13jW9LI5mGtk5ZwYunbXTjmqq+qe5Z7KfLzAoCZRIm6l+jXTR1kiesJxaBDqepgjUL/kznQugozjMBmMJN4LKXzqTvl7nBoQzyz+3opPQAz9vKsh96M6sS8m1i73S6c4aKq/YH1JSh0+963drsdRanQLlDr7GzY3epqmqq+dWbz0D/WO0qns41qch4aEWgwRqVMG3Q664eWoevGkWHUpabma06vk+P5mEoeTo40o/6sNXg1d9alFYQTa3BgOcdD7Th/0hAs5NWVY1O6Z9qa+guY+YmFBUZKG2fK4YQQhCDi+c3PvDDEUTHKho5OZjNhwLR6BFnNLt363j3RN9GFrW/j/ke+P296PMjOc4zwsD4mf9HM1hIFEwzwZGMPHn6z69SfWRk4faEzpK6DS+qedY/n7qOqwkQWt2arqQOdqUKiqG7ucUoXDGudtBTqEH9AbX3ts6DQNuf0itPheBpMx5PrenscHuEpWZBlWRia6LuZroLhxdhJct1Db8B9x9gb1BbrkhzE/WV3w6+DhZg3PC8ErcKekP/UO8JVGhP72fI5n44xO5vlaFf+51Ef9H7wYBc8XjieLzw39END1xzmAQQbtLSKgOYEyAAJFx91dzhZ5Xu4Kd0z/w7xNcbmYNkBtyamfIrLrXQXRqiyniyuIdXMISOH54fmH4PsEJEFly/z1Ndx8DVxRcX/jXqJoMy9o+J+Adg9one3VbU/tC+YUoYuP5CbCI4u3R1Ny4f35Hpy62pCj0+uSPGyPfbEyBWqseAxwJRP9iq2TUhgZBRbQumiYX2ktGDDeCZA+Z2rfAYfURdTUyLf6kGW38zVG+0bJFxlf+z7rqWVcxVmJ9yegF09qbgGjs5dYqxxmOrEo7XLtzeaHCyBeW19YD1UQSuxJ2634b3IW0i11Ra+ACvzTdJZXDszcxt2QAAzgHxaF3GSAFeUbXyEqAcjdxKEhSwmeErg+vxz7Enp3cTYhj0kw1M/TJOTCmis/gHt0NUlI5590LQDY7hrCi01mGYlJ87qTWv5CSR07T26iq+cXt/0lzxLn0VFD0b2bndwOrnh+bAtNa9F9oREd00zjLe6WTAkmdMzi6/Ut3zBsLJz81aVFpjhDXvP61tT/Sb+4ejbunVsGKeuc9BRtrqDD9XITO45FgdDFy+3HtJv595eNzm88c4bvElCyfNvQ/UfHsjnZSHbaUUlA1boNaZAHWhF9kSS4vSXs5B4uxf8xhAWz9uBU6KzPoK/AhMWoQwuySJCfLhxj1SWqVY80khUmG4sarSgm5v8Goa5JeFOmnnlqKunhmyyi6zuOPg01N5azok5OLA8oXtO2Iirsb5njr5MgrzLTFjyMTfbZE/x+1H/Kttc4qKL764sLZC/kvkQFr+g5RKwHiiEdHTLKwfc0ZjrjzxUSwlR9A8T/4upKrr7s9oIOL2p9uimavF4Zm8nu1qqXy6+Uw9akT3zSbhoIelucOWNp/OlLHdcWlJHOTslOpiO4YwCsOLRfYGqA+qeaMHkdc+76fjM8SG8hkdbFXbugFTzM6dz3f2TumeuGe1ehufDThpAXLNqyCn5g7NlzdY//eObZ09K5z9voraMFfwbFUtLS+jtd9KI/NOD2/zGZEu+0h2eTjwkWWU7dddUHn06wW4CrcieqOKh8hj/HA8gvXc2fa8W/Q6VjvAbLJWVnX+IviwyOJ+6Ovj60STXzTPHOdJZWhuFA2d7+c2NwVmHbA1wpQEfhf4pnx8JXmnOy/x9r1L3ZJ0rbFXK9XflyzhK93qu/Ozf+MBTsGfruC4rLVkefutN+BMVPk13mt/yOy44GMGbpxnHpnE0Hp9oylZHP/AWJ2QieMCGSqezpVvvU0+IOkQShAAR5plCGe5/QLblfz6PUnrnW7u6ceJYBwPzrOhLBK22eIY/G65XqXv+CUmU72QIvEj2lIP38hFAp2cphs57BaR5OkM3d44EMemiuG2GP1D8DTke+XzK9FvJnikU8qINBCR7toGirGNVBHAXQM2fLaD0zhtqpnWo28VTGiB6lnd9il869/Zq8ikle4oRk3cfiYBkz0cCJx9bCwHYCpjTK5etC3yyzepn9N3U6o4Rkey5LM6y3FIISPZcCiZZ6Lkg8BCMD+3av0X4y7ffubV7SSR7PpdRfCXtkOz5SgZSdmMxApI9F2MkS6yAgGTPFcCSRV82ApI9X/b4PbvWS/Z8dkMiG7QpBCR7bgrZv7ReYM/8T80x5n8pOrLbLx4BttUtE/HCQS1p7/6XXskLiYBEQCIgEVgeAcmey2MlS0oEJAISgQwByZ4ZFvJKIiARkAgsj4Bkz+WxkiUlAhIBiUCGgGTPDAt5JRGQCEgElkdAsufyWMmSEgGJgEQgQ0CyZ4aFvJIISAQkAssjINlzeaxkSYmAREAikCEg2TPDQl5JBCQCEoHlEfg/iSz909y0OngAAAAASUVORK5CYII="
    }
   },
   "cell_type": "markdown",
   "id": "160db91f",
   "metadata": {},
   "source": [
    "4. 深度确定性策略梯度（DDPG）\n",
    "\n",
    "接下来我们将使用深度确定性策略梯度（DDPG）算法，它构建了一个确定性策略，通过梯度上升来最大化价值。DDPG 也是一种 Actor-Critic 算法。\n",
    "\n",
    "若策略是确定性的，可表示为$a = \\mu_\\theta(s)$。类似于策略梯度定理，我们可以推导出确定性策略梯度定理：\n",
    "\n",
    "![image.png](attachment:image.png)\n",
    "\n",
    "其中$\\pi_\\beta$是用于收集数据的策略。我们可以这样理解这个定理：假设已有一个函数Q给定状态s。但由于现在动作空间是无限的，无法通过遍历所有动作来找到使Q最大的动作，因此我们希望使用策略μ来找到最大化Q(s, a)的动作μ(s) = argmax_a{Q(s, a)}。\n",
    "为了得到μ，我们首先使用链式法则对▽_θ{Q(s,μ_θ(s)}关于μ_θ求导，先对a求导，再对θ求导。然后通过梯度上升来最大化该函数，从而得到使Q值最大的动作。\n",
    "\n",
    "DDPG 使用四个神经网络：Actor 和 Critic 各一个，以及各自的目标网络。在 DDPG 中，Actor 也需要目标网络，因为目标网络也用于计算目标值Q。DDPG 中目标 Q 网络的更新与 DQN 略有不同：在 DQN 中，Q 网络定期直接复制到目标 Q' 网络；而在 DDPG 中，目标 Q' 网络使用软更新方法，即目标 Q' 网络缓慢更新并逐渐接近 Q 网络，其公式为：\n",
    "\n",
    "![image-2.png](attachment:image-2.png)\n",
    "\n",
    "通常$ \\tau $是一个相对较小的数，当$ \\tau=1 $时，与 DQN 的更新方式一致。目标网络 μ 也使用这种软更新方法。\n",
    "\n",
    "此外，由于函数Q值高估的问题，DDPG 采用了 Double DQN 中的技术来更新网络。然而，由于 DDPG 使用确定性策略，其自身的探索能力仍然非常有限。回顾 DQN 算法，其探索主要由 ε- 贪婪策略的行为生成。作为一种离线策略算法，DDPG 在行为策略上引入随机噪声进行探索。\n",
    "\n",
    "策略网络和价值网络均使用单隐藏层神经网络。策略网络的输出层使用正切函数 tanh 作为激活函数，因为正切函数的值域是[-1,1]，便于缩放到环境可接受的动作范围。在处理连续动作交互环境的 DDPG 中，Critic 网络的输入是状态和动作拼接的向量，输出是表示该状态 - 动作对价值的单个值。\n",
    "当使用策略网络执行动作时，我们向动作添加高斯噪声以进行更好的探索。在原始 DDPG 论文中，添加的噪声对应于 Ornstein-Uhlenbeck（OU）随机过程：\n",
    "△x_t = θ(μ - x_t-1 ) + σ · W![image-3.png](attachment:image-3.png)\n",
    "其中μ是均值，W是遵循布朗运动的随机噪声，θ 和 σ 是缩放参数。可以看出，当偏离均值时，x_t的值会向均值靠近。OU 随机过程的特点是围绕均值的线性负反馈加上一个额外的干扰项。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7effcab8",
   "metadata": {},
   "outputs": [],
   "source": [
    "class DDPG:\n",
    "    \"\"\"The DDPG Algorithm.\n",
    "\n",
    "    1. Each instance of DDPG corresponds an agent.\n",
    "    2. Each instance of DDPG consists of an actor (policy network) and a critic (value network).\n",
    "    3. Each instance of DDPG contains a set of target networks for its actor and critic (affected by the double DQN strategy).\n",
    "    4. Network update function is contained in the Center Controller class, the MADDPG class, so that we can achieve the Centralized Training and Decentralized Execution method easily.\n",
    "\n",
    "    Attributes:\n",
    "        actor:              The Actor (Policy Network).\n",
    "        target_actor:       The Target Actor (Target Policy Network).\n",
    "        critic:             The Critic (value Network).\n",
    "        target_critic:      The Target Critic (Target Value Network).\n",
    "        actor_optimizer:    The optimizer of Actor.\n",
    "        critic_optimizer:   The optimizer of Critic.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, state_dim, action_dim, critic_dim, hidden_dim, actor_lr, critic_lr, device):\n",
    "        \"\"\"Initialize a DDPG instance for an agent.\n",
    "\n",
    "        Args:\n",
    "            state_dim:      The dimension of the state, which is also the input dimension of Actor and a part of Critics' input.\n",
    "            action_dim:     The dimension of the action, which is also a part of Critics' input.\n",
    "            critic_dim:     The dimension of the Critics' input (Critic Dimension = State Dimensions + Action Dimension).\n",
    "            hidden_dim:     The dimension of the hidden layer of the networks.\n",
    "            actor_lr:       The learning rate for the Actor.\n",
    "            critic_lr:      The learning rate for the Critic.\n",
    "            device:         The device to compute.\n",
    "        \"\"\"\n",
    "        # Set Actor with Target Network\n",
    "        self.actor = SimpleNet(state_dim, action_dim, hidden_dim).to(device)\n",
    "        self.target_actor = SimpleNet(state_dim, action_dim, hidden_dim).to(device)\n",
    "        # Set Critic with Target Network\n",
    "        self.critic = SimpleNet(critic_dim, 1, hidden_dim).to(device)\n",
    "        self.target_critic = SimpleNet(critic_dim, 1, hidden_dim).to(device)\n",
    "        # Load parameters from Actor and Critic to their target networks\n",
    "        self.target_actor.load_state_dict(self.actor.state_dict())\n",
    "        self.target_critic.load_state_dict(self.critic.state_dict())\n",
    "        # Set up optimizers\n",
    "        self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=actor_lr)\n",
    "        self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=critic_lr)\n",
    "\n",
    "    def take_action(self, state, explore=False):\n",
    "        \"\"\"Take action from the Actor (Policy Network).\n",
    "\n",
    "        1. State -> the Actor -> Action Value\n",
    "        2. Choose action according to the value of explore.\n",
    "            - explore == True: Choose an action based on the gumbel trick.\n",
    "            - explore == False: Choose the action from the Actor, and transform the value to a one-hot vector.\n",
    "\n",
    "        Args:\n",
    "            state:      The partial observation of the agent.\n",
    "            explore:    The strategy to choose action.\n",
    "\n",
    "        Returns: The action that the Actor has chosen.\n",
    "\n",
    "        \"\"\"\n",
    "        # Choose an action from actor network (deterministic policy network).\n",
    "        action = self.actor(state)\n",
    "        # Exploration and Exploitation\n",
    "        if explore:\n",
    "            action = gumbel_softmax(action)\n",
    "        else:\n",
    "            action = trans2onehot(action)\n",
    "        # TODO: Find out why the action need to be transferred to the CPU\n",
    "        # return action.detach().cpu().numpy()[0]\n",
    "        return action.detach().cpu().numpy()[0]\n",
    "\n",
    "    @staticmethod\n",
    "    def soft_update(net, target_net, tau):\n",
    "        \"\"\"Soft update function, which is used to update the parameters in the target network.\n",
    "\n",
    "        Args:\n",
    "            net:            The original network.\n",
    "            target_net:     The target network.\n",
    "            tau:            Soft update parameter.\n",
    "\n",
    "        Returns: None\n",
    "\n",
    "        \"\"\"\n",
    "        # Update target network's parameters using soft update strategy\n",
    "        for target_param, param in zip(target_net.parameters(), net.parameters()):\n",
    "            target_param.data.copy_(tau * param.data + (1.0 - tau) * target_param.data)"
   ]
  },
  {
   "attachments": {
    "image-2.png": {
     "image/png": "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"
    },
    "image-3.png": {
     "image/png": "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"
    },
    "image.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "id": "e3ea1782",
   "metadata": {},
   "source": [
    "5. 多智能体深度确定性策略梯度（MADDPG）\n",
    "\n",
    "多智能体DDPG（MADDPG）算法从字面上理解，是为每个智能体实现一个DDPG的算法。所有智能体共享一个中心化的Critic网络，该网络在训练过程中同时指导每个智能体的Actor网络，而每个智能体的Actor网络则完全独立地执行，即去中心化执行。MADDPG算法的核心细节在于，每个智能体都使用Actor-Critic方法进行训练，但与传统单智能体不同的是，MADDPG中每个智能体的Critic部分可以获取其他智能体的策略信息。具体来说，如果我们考虑一个有$N$个智能体的游戏，每个智能体的策略参数为$\\Theta = \\{\\theta_1, \\theta_2, \\ldots, \\theta_N\\}$，$\\pi = \\{\\pi_1, \\pi_2, \\ldots, \\pi_N\\}$是所有智能体的策略集合，那么我们可以写出在随机策略情况下每个智能体的期望回报的策略梯度：  \n",
    "![image.png](attachment:image.png)\n",
    "\n",
    "$Q_i^{\\pi} = (X, a_1, \\ldots, a_N)$是一个中心化的动作价值函数。为什么$Q_i$是中心化的动作价值函数呢？一般来说，$X = (o_1, \\ldots, o_N)$包含所有智能体的观测，并且$Q_i$也必须包含该时刻所有智能体的动作，因此$Q_i$的前提是所有智能体必须同时给出自己的观测和相应的动作。  \n",
    "\n",
    "对于确定性策略，考虑到现在有$N$个连续的策略$\\mu_(\\theta_i)$，我们可以得到DDPG的梯度公式：  \n",
    "![image-2.png](attachment:image-2.png)\n",
    "$\\mathcal{D}$是我们用于存储数据的经验回放池，它存储的每一条数据都是$(x, x', a_1, \\ldots, a^N, r^1, \\ldots, r^N)$。在MADDPG中，中心化的动作价值函数可以使用以下损失函数进行更新：  \n",
    "![image-3.png](attachment:image-3.png)\n",
    "$\\mu' = \\{\\mu_1', \\mu_2', \\ldots, \\mu_N'\\}$是更新价值函数时使用的目标策略集合，它们具有延迟更新的参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e3825eca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nMADDPG 采用轮流更新每个智能体的策略：\\n- 在每次更新步骤中，只优化一个智能体的网络（包括 Critic 和 Actor）\\n- 通过多次迭代，最终所有智能体的网络都会得到优化\\n\\n这种设计的优点：\\n- 计算效率更高：每次只更新一个网络，减少计算负担\\n- 训练稳定性更好：避免多个智能体同时更新导致的训练波动\\n- 灵活性更强：可以根据需要优先更新特定智能体\\n'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class MADDPG:\n",
    "    \"\"\"The Multi-Agent DDPG Algorithm.\n",
    "\n",
    "    1. The instance of MADDPG is the Center Controller in the algorithm.\n",
    "    2. The instance of MADDPG contains a list of DDPG instances, which are corresponded with the agents in the environment one by one.\n",
    "\n",
    "    Attributes:\n",
    "        agents:     A list of DDPG instances, which are corresponded with the agents in the environment one by one.\n",
    "        device:     The device to compute.\n",
    "        gamma:      The gamma parameter in TD target.\n",
    "        tau:        The tau parameter for soft update.\n",
    "        critic_criterion: The loss function for the Critic networks.\n",
    "    \"\"\"\n",
    "    # MADDPG 类作为中央控制器，管理多个 DDPG 智能体：\n",
    "    def __init__(self, state_dims, action_dims, critic_dim, hidden_dim, actor_lr, critic_lr, device, gamma, tau):\n",
    "        \"\"\"Initialize a MADDPG instance as the Center Controller.\n",
    "\n",
    "        Args:\n",
    "            state_dims: A list of dimensions of each agent's observation.\n",
    "            action_dims: A list of dimensions of each agent's action.\n",
    "            critic_dim: The dimension of the Critic networks' input.\n",
    "            hidden_dim: The dimension of the networks' hidden layers.\n",
    "            actor_lr: The learning rate for the Actor.\n",
    "            critic_lr: The learning rate for the Critic.\n",
    "            device: The device to compute.\n",
    "            gamma: The gamma parameter in TD target.\n",
    "            tau: The tau parameter for soft update.\n",
    "        TODO: Should we use dict to combine the DDPG instance with agents?\n",
    "        \"\"\"\n",
    "        # agents: 存储每个智能体的 DDPG 实例\n",
    "        self.agents = [\n",
    "            DDPG(state_dim, action_dim, critic_dim, hidden_dim, actor_lr, critic_lr, device)\n",
    "            for state_dim, action_dim in zip(state_dims, action_dims)\n",
    "        ]\n",
    "        self.device = device\n",
    "        # gamma: 折扣因子，权衡短期和长期奖励\n",
    "        self.gamma = gamma\n",
    "        # tau: 软更新参数，控制目标网络的更新速度\n",
    "        self.tau = tau\n",
    "        self.critic_criterion = nn.MSELoss()\n",
    "\n",
    "    # 属性与行动选择\n",
    "    # policies和target_policies属性分别返回所有智能体的 Actor 网络和目标 Actor 网络\n",
    "    @property\n",
    "    def policies(self):\n",
    "        \"\"\"A list of Actors for the agents.\"\"\"\n",
    "        return [agent.actor for agent in self.agents]\n",
    "\n",
    "    @property\n",
    "    def target_policies(self):\n",
    "        \"\"\"A list of Target Actors for the agents.\"\"\"\n",
    "        return [agent.target_actor for agent in self.agents]\n",
    "\n",
    "    # take_action方法根据当前状态为所有智能体选择行动，支持探索策略\n",
    "    def take_action(self, states, explore):\n",
    "        \"\"\"Take actions from the Actors (Policy Networks).\n",
    "\n",
    "        Args:\n",
    "            states: A list of observations from all the agents.\n",
    "            explore: The strategy to choose action (Exploration or Exploitation).\n",
    "\n",
    "        Returns: A list of actions in one-hot vector form.\n",
    "\n",
    "        \"\"\"\n",
    "        states = [torch.tensor(np.array([state]), dtype=torch.float, device=self.device) for state in states]\n",
    "        return [agent.take_action(state, explore) for agent, state in zip(self.agents, states)]\n",
    "\n",
    "    def update(self, sample, agent_idx):\n",
    "        \"\"\"Update parameters for the agent whose index is agent_idx.\n",
    "\n",
    "        Args:\n",
    "            sample: A batch of transitions used to update all the parameters.\n",
    "            agent_idx: The index of the agent whose Actor and Critic would be updated in this function.\n",
    "\n",
    "        Returns: None\n",
    "\n",
    "        Process:\n",
    "            Parse Data from Sample to Observation, Action, Reward, Next Observation and Done Tag.\n",
    "            Set up Current Agent\n",
    "            Update Current Critic (Value Network) with TD Algorithm:\n",
    "                1. Initialize the Gradient to Zero.\n",
    "                2. Build a Tensor Contains All Target Actions Using Target Actor Networks and Next Observations.\n",
    "                3. Calculate Target Critic Value:\n",
    "                    - Combine Next Observation and Target Action in One To One Correspondence.\n",
    "                    - Calculate Target Critic Value (TD Target).\n",
    "                4. Calculate Critic Value:\n",
    "                    - Combine Observation and Action in One To One Correspondence.\n",
    "                    - Calculate Critic Value (TD Target).\n",
    "                5. Calculate Critic's Loss Using MSELoss Function\n",
    "                6. Backward Propagation.\n",
    "                7. Update Parameters with Gradient Descent.\n",
    "            Update Current Actor (Policy Network) with Deterministic Policy Gradient:\n",
    "                1. Initialize the Gradient to Zero.\n",
    "                2. Get Current Actors' Action in the Shape of One-Hot Vector.\n",
    "                    - Get Current Actor Network Output with Current Observation.\n",
    "                    - Transform the Output into a One-Hot Action Vector.\n",
    "                3. Build the Input of Current Actor's Value Function.\n",
    "                    - Build a tensor that contains all the actions.\n",
    "                    - Combine Observations and Actions in One To One Correspondence.\n",
    "                4. Calculate Actor's Loss Using Critic Network (Value Function) Output.\n",
    "                5. Backward Propagation.\n",
    "                6. Update Parameters with Gradient Descent.\n",
    "\n",
    "        TODO:\n",
    "        1. Why there is a term, \"(1 - dones[agent_idx].view(-1, 1))\", during calculation of TD target?\n",
    "            To take termination in to consideration (To be verified).\n",
    "        2. Why there is a term, \"(current_actor_action_value ** 2).mean() * 1e-3\", during calculation of Actor Loss?\n",
    "            To make the output of the trained Actor more stable and smooth with this regular term (To be verified).\n",
    "        \"\"\"\n",
    "        \"\"\"更新索引为agent_idx的智能体的参数。\n",
    "\n",
    "        参数:\n",
    "            sample: 用于更新所有参数的一批转移样本。\n",
    "            agent_idx: 此函数中要更新其Actor和Critic的智能体索引。\n",
    "\n",
    "        返回: None\n",
    "\n",
    "        处理流程:\n",
    "            从样本中解析数据为观测、动作、奖励、下一观测和终止标签。\n",
    "            设置当前智能体\n",
    "            使用TD算法更新当前Critic(价值网络):\n",
    "                1. 将梯度初始化为零。\n",
    "                2. 使用目标Actor网络和下一观测构建包含所有目标动作的张量。\n",
    "                3. 计算目标Critic值:\n",
    "                    - 将下一观测和目标动作一一对应组合。\n",
    "                    - 计算目标Critic值(TD目标)。\n",
    "                4. 计算Critic值:\n",
    "                    - 将观测和动作一一对应组合。\n",
    "                    - 计算Critic值(TD目标)。\n",
    "                5. 使用MSELoss函数计算Critic损失。\n",
    "                6. 反向传播。\n",
    "                7. 使用梯度下降更新参数。\n",
    "            使用确定性策略梯度更新当前Actor(策略网络):\n",
    "                1. 将梯度初始化为零。\n",
    "                2. 获取当前Actor的one-hot向量形式的动作。\n",
    "                    - 使用当前观测获取当前Actor网络输出。\n",
    "                    - 将输出转换为one-hot动作向量。\n",
    "                3. 构建当前Actor价值函数的输入。\n",
    "                    - 构建包含所有动作的张量。\n",
    "                    - 将观测和动作一一对应组合。\n",
    "                4. 使用Critic网络(价值函数)输出计算Actor损失。\n",
    "                5. 反向传播。\n",
    "                6. 使用梯度下降更新参数。\n",
    "\n",
    "        待确认问题:\n",
    "        1. 为什么在计算TD目标时有一项\"(1 - dones[agent_idx].view(-1, 1))\"?\n",
    "            是为了考虑终止状态(待验证)。\n",
    "        2. 为什么在计算Actor损失时有一项\"(current_actor_action_value ** 2).mean() * 1e-3\"?\n",
    "            是为了通过这个正则化项使训练后的Actor输出更加稳定和平滑(待验证)。\n",
    "        \"\"\"\n",
    "        '''\n",
    "        TD 目标中的(1 - dones)项:\n",
    "            这是处理强化学习中终止状态的标准做法。当环境 episode 结束时 (done=True), 下一状态的价值应为 0, 因为没有后续奖励了。\n",
    "            数学上，TD 目标在终止状态时应简化为reward, 而非reward + gamma * next_value\n",
    "        Actor 损失中的 L2 正则化项:\n",
    "            这是一种常用的正则化技术，通过惩罚过大的动作值来防止过拟合并提高策略稳定性。\n",
    "            类似于神经网络中的权重衰减，但这里直接作用于动作输出，有助于在连续动作空间中生成更平滑的控制信号。\n",
    "        '''\n",
    "        # 从经验回放缓冲区中采样一批转换数据，并确定当前要更新的智能体。\n",
    "        states, actions, rewards, next_states, dones = sample \n",
    "        '''\n",
    "        current_agent 的作用\n",
    "            current_agent 始终指向由agent_idx指定的智能体\n",
    "            所有操作（梯度清零、前向传播、反向传播、优化器更新）都针对这个特定智能体\n",
    "        '''\n",
    "        current_agent = self.agents[agent_idx]\n",
    "\n",
    "        # Update Current Critic (Value Network) with TD Algorithm\n",
    "\n",
    "\n",
    "        # Critic 网络更新\n",
    "        # 首先清空 Critic 优化器的梯度\n",
    "        current_agent.critic_optimizer.zero_grad() \n",
    "        # Here is the step to choose the actions from the actor network and we have two strategies.\n",
    "        # Option 1: Use the target network strategy.\n",
    "        # 使用所有智能体的目标 Actor 网络生成下一状态的行动\n",
    "        target_action = [\n",
    "            trans2onehot(_target_policy(_next_obs))\n",
    "            for _target_policy, _next_obs in zip(self.target_policies, next_states)\n",
    "        ] \n",
    "        # Option 2: Use the double DQN strategy.\n",
    "        # target_action = [\n",
    "        #     # Choose actions from the original network!!!\n",
    "        #     trans2onehot(policy(_next_obs))\n",
    "        #     for policy, _next_obs in zip(self.policies, next_states)\n",
    "        # ]\n",
    "        '''\n",
    "        目标网络的使用\n",
    "            在计算目标 Critic 值时，确实使用了所有智能体的目标 Actor 网络来生成下一状态的动作\n",
    "            但最终只使用当前智能体的目标 Critic 网络计算目标值\n",
    "            这是 MADDPG\"中心化训练\" 特性的体现：每个智能体的 Critic 可以访问全局信息\n",
    "        '''\n",
    "        # 构建目标 Critic 网络的输入（所有智能体的下一状态和目标行动）\n",
    "        target_critic_input = torch.cat((*next_states, *target_action), dim=1)\n",
    "        # 计算 TD 目标值：当前奖励 + 折扣后的下一状态价值, (1 - dones[agent_idx].view(-1, 1)) 项处理终止状态：当 episode 结束时，只考虑即时奖励\n",
    "        target_critic_value = (rewards[agent_idx].view(-1, 1) +\n",
    "                               self.gamma * current_agent.target_critic(target_critic_input) *\n",
    "                               (1 - dones[agent_idx].view(-1, 1)))\n",
    "        # 构建当前 Critic 网络的输入（所有智能体的当前状态和行动）\n",
    "        critic_input = torch.cat((*states, *actions), dim=1)\n",
    "        # 计算 Critic 网络的预测值\n",
    "        critic_value = current_agent.critic(critic_input)\n",
    "        # 使用 MSE 损失函数计算预测值与目标值之间的差异\n",
    "        critic_loss = self.critic_criterion(critic_value, target_critic_value.detach())\n",
    "        # 反向传播并更新 Critic 网络参数\n",
    "        critic_loss.backward()\n",
    "        '''\n",
    "        优化器更新范围\n",
    "            current_agent.critic_optimizer.step() 明确指定只更新当前智能体的 Critic 网络参数\n",
    "            其他智能体的 Critic 网络参数在这次调用中不会被修改\n",
    "        '''\n",
    "        current_agent.critic_optimizer.step()\n",
    "\n",
    "\n",
    "        # Actor 网络更新\n",
    "        # Update Current Actor (Policy Network) with Deep Deterministic Policy Gradient\n",
    "        # 清空 Actor 优化器的梯度\n",
    "        current_agent.actor_optimizer.zero_grad()\n",
    "        # 当前智能体的 Actor 网络根据当前状态生成行动概率\n",
    "        current_actor_action_value = current_agent.actor(states[agent_idx])\n",
    "        # 使用 Gumbel-Softmax 技巧将概率分布转换为近似的 one-hot 向量\n",
    "        current_actor_action_onehot = gumbel_softmax(current_actor_action_value)\n",
    "\n",
    "        '''\n",
    "        动作列表构建方式\n",
    "            只有索引为agent_idx的智能体使用新生成的动作 (current_actor_action_onehot)\n",
    "            其他智能体的动作保持不变（使用当前策略生成的动作）\n",
    "            这种设计是为了在计算梯度时只考虑当前智能体的策略变化\n",
    "        '''\n",
    "        # 构建所有智能体的动作（当前智能体使用gumbel_softmax可计算梯度，其他使用trans2onehot不可计算梯度）\n",
    "        all_actor_actions = [\n",
    "            current_actor_action_onehot if i == agent_idx else trans2onehot(_policy(_state))\n",
    "            for i, (_policy, _state) in enumerate(zip(self.policies, states))\n",
    "        ]\n",
    "        # 构建 Critic 网络的输入（所有智能体的当前状态和行动）\n",
    "        current_critic_input = torch.cat((*states, *all_actor_actions), dim=1)\n",
    "        # 计算 Actor 损失：最大化 Critic 对当前策略的评价 + L2 正则化项\n",
    "        # (current_actor_action_value ** 2).mean() * 1e-3 是正则化项，防止行动值过大，提高稳定性\n",
    "        actor_loss = (-current_agent.critic(current_critic_input).mean() +\n",
    "                      (current_actor_action_value ** 2).mean() * 1e-3)\n",
    "        '''\n",
    "        梯度计算与优化\n",
    "            actor_loss.backward() 计算损失函数关于所有参数的梯度\n",
    "            但由于只对current_agent.actor_optimizer调用了step()\n",
    "            因此只有当前智能体的 Actor 网络参数会被更新\n",
    "        '''\n",
    "        # 反向传播并更新 Actor 网络参数\n",
    "        actor_loss.backward()\n",
    "        current_agent.actor_optimizer.step()\n",
    "\n",
    "    def update_all_targets_params(self):\n",
    "        \"\"\"Update all Target network's parameters using soft update method.\"\"\"\n",
    "        for agent in self.agents:\n",
    "            # 使用软更新方法更新所有智能体的目标网络参数\n",
    "            # 软更新公式：θ' = τ*θ + (1-τ)*θ'，其中 θ 是源网络参数，θ' 是目标网络参数\n",
    "            agent.soft_update(agent.actor, agent.target_actor, self.tau)\n",
    "            agent.soft_update(agent.critic, agent.target_critic, self.tau)\n",
    "\n",
    "'''\n",
    "MADDPG 采用轮流更新每个智能体的策略：\n",
    "- 在每次更新步骤中，只优化一个智能体的网络（包括 Critic 和 Actor）\n",
    "- 通过多次迭代，最终所有智能体的网络都会得到优化\n",
    "\n",
    "这种设计的优点：\n",
    "- 计算效率更高：每次只更新一个网络，减少计算负担\n",
    "- 训练稳定性更好：避免多个智能体同时更新导致的训练波动\n",
    "- 灵活性更强：可以根据需要优先更新特定智能体\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "869e3489",
   "metadata": {},
   "source": [
    "6. 评估函数\n",
    "\n",
    "该函数以 MADDPG 智能体为输入，在指定的回合数和回合长度范围内评估其性能。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5b1f4e37",
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate(num_agents, maddpg, num_episode=10, len_episode=25):\n",
    "    \"\"\"Evaluate the strategies for learning, and no exploration is undertaken at this time.\n",
    "\n",
    "    Args:\n",
    "        num_agents: The number of the agents.\n",
    "        maddpg: The Center Controller.\n",
    "        num_episode: The number of episodes.\n",
    "        len_episode: The length of each episode.\n",
    "\n",
    "    Returns: Returns list.\n",
    "\n",
    "    \"\"\"\n",
    "    # 初始化环境，设置智能体数量和每episode的最大步数\n",
    "    env = simple_adversary_v3.parallel_env(N=num_agents, max_cycles=25, continuous_actions=False)\n",
    "    # 重置环境\n",
    "    env.reset()\n",
    "    # 创建一个数组来存储每个智能体的累计回报，初始化为0\n",
    "    returns = np.zeros(env.max_num_agents)\n",
    "    # Create an array returns of zeros with a length equal to the number of agents in the environment.\n",
    "    # This array will store the cumulative returns for each agent.\n",
    "    for episode in range(num_episode):\n",
    "        # 重置环境，获取初始状态和奖励\n",
    "        states_dict, rewards_dict = env.reset()\n",
    "        # 从字典中提取状态值，转换为列表形式（按智能体顺序排列）\n",
    "        states = [state for state in states_dict.values()]\n",
    "        # 内层循环：遍历每个episode中的时间步\n",
    "        for episode_step in range(len_episode):\n",
    "            # 通过MADDPG控制器获取动作，explore=False表示不进行探索（仅利用已学习的策略）\n",
    "            actions = maddpg.take_action(states, explore=False)\n",
    "            # Take actions using the MADDPG agent (maddpg.take_action) based on the current states. \n",
    "            # 将one-hot编码的动作转换为标量索引（选择最大值对应的索引）\n",
    "            actions_SN = [np.argmax(onehot) for onehot in actions]\n",
    "            # 构建动作字典，将标量动作映射到对应的智能体ID\n",
    "            actions_dict = {env.agents[i]: actions_SN[i] for i in range(env.max_num_agents)}\n",
    "            # 执行动作，获取下一状态、奖励、终止标志和截断标志\n",
    "            next_states_dict, rewards_dict, terminations_dict, truncations_dict, _ = env.step(actions_dict)\n",
    "            # Take a step in the environment by passing the actions dictionary to env.step.\n",
    "            # 从字典中提取奖励值和下一状态值，转换为列表形式  \n",
    "            rewards = [reward for reward in rewards_dict.values()]\n",
    "            next_states = [next_state for next_state in next_states_dict.values()]\n",
    "            # 更新状态为下一状态，准备下一个时间步\n",
    "            states = next_states\n",
    "            # 将奖励转换为numpy数组，并累加到总回报中（使用平均累积，除以episode总数）\n",
    "            rewards = np.array(rewards)\n",
    "            returns += rewards / num_episode\n",
    "    env.close()\n",
    "    return returns.tolist()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fb31e9d",
   "metadata": {},
   "source": [
    "7. 辅助函数\n",
    "\n",
    "该函数对输入列表 x 中的元素进行重新排列，并将它们转换为指定设备上的 PyTorch 张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d2759707",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sample_rearrange(x, device):\n",
    "    \"\"\"Rearrange the transition in the sample.\"\"\"\n",
    "    # rearranged = [[sub_x[i] for sub_x in x] for i in range(len(x[0]))]\n",
    "    # return [torch.FloatTensor(np.vstack(attribute)).to(device) for attribute in rearranged]\n",
    "    return [torch.FloatTensor(np.vstack(col)).to(device) for col in zip(*x)]\n",
    "    # np.vstack is used to vertically stack the elements in each sublist before converting them to a tensor.\n",
    "    # The resulting tensors are then converted to the appropriate device (GPU)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65e470db",
   "metadata": {},
   "source": [
    "8. 参数设置与变量初始化\n",
    "\n",
    "现在需要使用指定的配置，为在多智能体环境中训练 MADDPG 智能体初始化必要的组件和参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "fc3662e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set up Parameters\n",
    "NUM_EPISODES = 5000\n",
    "LEN_EPISODES = 25  # The maximum length of each episode\n",
    "BUFFER_SIZE = 100000\n",
    "HIDDEN_DIM = 64  # denotes the dimension of the hidden layers in the actor and critic networks.\n",
    "ACTOR_LR = 1e-2\n",
    "CRITIC_LR = 1e-2\n",
    "GAMMA = 0.95  # determines the discount factor for future rewards.\n",
    "TAU = 1e-2  # sets the soft update coefficient for target network updates.\n",
    "BATCH_SIZE = 1024\n",
    "UPDATE_INTERVAL = 100  # determines the number of steps before performing an update on the networks.\n",
    "MINIMAL_SIZE = 4000  # is a minimum threshold for the replay buffer size before starting the training.\n",
    "# Initialize Environment\n",
    "env = simple_adversary_v3.parallel_env(N=2, max_cycles=25, continuous_actions=False)\n",
    "env.reset()\n",
    "# Initialize Replay Buffer\n",
    "buffer = ReplayBuffer(BUFFER_SIZE)  # stores experiences from the environment.\n",
    "# Initialize Device\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "# Initialize Return List\n",
    "return_list = []\n",
    "# Initialize Total Step\n",
    "total_step = 0\n",
    "# Initialize MADDPG\n",
    "# 1. Get State and Action Dimensions from the Environment\n",
    "state_dims = [env.observation_space(env.agents[i]).shape[0] for i in range(env.num_agents)]\n",
    "action_dims = [env.action_space(env.agents[i]).n for i in range(env.num_agents)]\n",
    "critic_dim = sum(state_dims) + sum(action_dims)  # calculates the total dimension of the critic network's input\n",
    "# 2. Create Center Controller\n",
    "maddpg = MADDPG(state_dims, action_dims, critic_dim, HIDDEN_DIM, ACTOR_LR, CRITIC_LR, device, GAMMA, TAU)\n",
    "# maddpg is created as an instance of the MADDPG class using the specified dimensions, learning rates and other parameters."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a0117d9",
   "metadata": {},
   "source": [
    "9. 训练  \n",
    "\n",
    "此代码实现了MADDPG智能体的训练循环，包括执行动作、与环境交互、更新网络以及定期评估智能体的性能。  \n",
    "\n",
    "- 调用MADDPG智能体的`take_action`方法时传入参数`explore=True`，这意味着智能体将在动作选择中添加探索噪声，使其能够探索不同动作，而非始终确定性地选择同一动作。  \n",
    "- 生成的动作初始采用独热编码（one-hot encoded）格式，表示每个智能体在可能动作上的概率分布。  \n",
    "- 通过使用`numpy.argmax`函数，每个独热编码动作会通过选择概率最高的索引转换为离散动作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "fb64d037",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Episode: 100, [-32.38290315215956, 5.847471578086041, 5.847471578086041]\n",
      "Episode: 200, [-53.009307782929355, 8.173164136726118, 8.173164136726118]\n",
      "Episode: 300, [-36.46205963854611, 6.1974346285896855, 6.1974346285896855]\n",
      "Episode: 400, [-25.73373009767922, -17.40270749116907, -17.40270749116907]\n",
      "Episode: 500, [-20.929676026425625, -4.2865523698201695, -4.2865523698201695]\n",
      "Episode: 600, [-24.733982115335426, 0.4153681811222949, 0.4153681811222949]\n",
      "Episode: 700, [-27.97116182743009, -1.9620677186896471, -1.9620677186896471]\n",
      "Episode: 800, [-24.586362631645294, -0.7856629127679504, -0.7856629127679504]\n",
      "Episode: 900, [-18.428113086299195, -3.5657268203423187, -3.5657268203423187]\n",
      "Episode: 1000, [-19.88945640340191, 3.3286113965139807, 3.3286113965139807]\n",
      "Episode: 1100, [-18.108611940480138, -1.7853718050509053, -1.7853718050509053]\n",
      "Episode: 1200, [-18.723583487136487, -3.952111241360198, -3.952111241360198]\n",
      "Episode: 1300, [-16.61658374599896, -1.2670923777712053, -1.2670923777712053]\n",
      "Episode: 1400, [-16.54861476767904, 1.8747300953987476, 1.8747300953987476]\n",
      "Episode: 1500, [-19.557060352489064, 5.657318755397829, 5.657318755397829]\n",
      "Episode: 1600, [-17.508055816860626, 3.5220962707344086, 3.5220962707344086]\n",
      "Episode: 1700, [-18.08168704289397, 4.781773511696899, 4.781773511696899]\n",
      "Episode: 1800, [-16.945873363340016, 4.1404652655862275, 4.1404652655862275]\n",
      "Episode: 1900, [-17.46372078304273, 2.4430899221986935, 2.4430899221986935]\n",
      "Episode: 2000, [-16.939519325464868, 5.121480220833227, 5.121480220833227]\n",
      "Episode: 2100, [-17.035218529323707, 4.545354969171443, 4.545354969171443]\n",
      "Episode: 2200, [-18.025176394935055, 5.74256281560859, 5.74256281560859]\n",
      "Episode: 2300, [-15.657695516356501, 4.321089461815802, 4.321089461815802]\n",
      "Episode: 2400, [-14.885916543426166, 3.678832047075817, 3.678832047075817]\n",
      "Episode: 2500, [-16.794852503747542, 5.413232115715397, 5.413232115715397]\n",
      "Episode: 2600, [-17.813140941384173, 4.907039308492741, 4.907039308492741]\n",
      "Episode: 2700, [-17.417121782945635, 7.26352084043525, 7.26352084043525]\n",
      "Episode: 2800, [-15.533956670784079, 4.779611256982209, 4.779611256982209]\n",
      "Episode: 2900, [-15.332460301970826, 5.208228184055709, 5.208228184055709]\n",
      "Episode: 3000, [-16.471666312681663, 5.026143582961967, 5.026143582961967]\n",
      "Episode: 3100, [-15.90147697559352, 5.1613500702527295, 5.1613500702527295]\n",
      "Episode: 3200, [-14.474506962255651, 3.4903083365980887, 3.4903083365980887]\n",
      "Episode: 3300, [-14.12791836197062, 4.269859196922919, 4.269859196922919]\n",
      "Episode: 3400, [-14.164766444166396, 4.393101929503218, 4.393101929503218]\n",
      "Episode: 3500, [-14.229064421443908, 4.040965708967099, 4.040965708967099]\n",
      "Episode: 3600, [-14.32480577861751, 5.630569777274775, 5.630569777274775]\n",
      "Episode: 3700, [-14.220929558385352, 4.638116069182226, 4.638116069182226]\n",
      "Episode: 3800, [-15.424467018760454, 6.319930767274251, 6.319930767274251]\n",
      "Episode: 3900, [-14.418238304173398, 5.188092432652706, 5.188092432652706]\n",
      "Episode: 4000, [-15.042971867694387, 6.066647880776352, 6.066647880776352]\n",
      "Episode: 4100, [-13.64995779868303, 4.360237898568932, 4.360237898568932]\n",
      "Episode: 4200, [-14.549175843202516, 5.032485553049323, 5.032485553049323]\n",
      "Episode: 4300, [-15.018225388661211, 4.977868119293141, 4.977868119293141]\n",
      "Episode: 4400, [-15.356659074854765, 5.319906918780279, 5.319906918780279]\n",
      "Episode: 4500, [-14.39064575008413, 5.004526758605096, 5.004526758605096]\n",
      "Episode: 4600, [-15.21727138382361, 5.978913872210818, 5.978913872210818]\n",
      "Episode: 4700, [-15.451583024914306, 6.925348481979395, 6.925348481979395]\n",
      "Episode: 4800, [-14.328982282769577, 5.125716941465537, 5.125716941465537]\n",
      "Episode: 4900, [-14.416153128451299, 6.079200520139437, 6.079200520139437]\n",
      "Episode: 5000, [-14.339391865359499, 6.026050849345886, 6.026050849345886]\n"
     ]
    }
   ],
   "source": [
    "for episode in range(NUM_EPISODES):\n",
    "    # Reset the Environment\n",
    "    states_dict, _ = env.reset()\n",
    "    states = [state for state in states_dict.values()]\n",
    "    # Start a New Game\n",
    "    for episode_step in range(LEN_EPISODES):\n",
    "        # Initial States and Actions\n",
    "        actions = maddpg.take_action(states, explore=True)\n",
    "        actions_SN = [np.argmax(onehot) for onehot in actions]\n",
    "        actions_dict = {env.agents[i]: actions_SN[i] for i in range(env.max_num_agents)}\n",
    "        # Step\n",
    "        next_states_dict, rewards_dict, terminations_dict, truncations_dict, _ = env.step(actions_dict)\n",
    "        # Add to buffer\n",
    "        rewards = [reward for reward in rewards_dict.values()]\n",
    "        next_states = [next_state for next_state in next_states_dict.values()]\n",
    "        terminations = [termination for termination in terminations_dict.values()]\n",
    "        buffer.add(states, actions, rewards, next_states, terminations)\n",
    "        # Update States\n",
    "        states = next_states\n",
    "        # Count += 1\n",
    "        total_step += 1\n",
    "        # When the replay buffer reaches a certain size and the number of steps reaches the specified update interval\n",
    "        # 1. Sample from the replay buffer.\n",
    "        # 2. Update Actors and Critics.\n",
    "        # 3. Update Target networks' parameters.\n",
    "        if len(buffer) >= MINIMAL_SIZE and total_step % UPDATE_INTERVAL == 0:\n",
    "            sample = buffer.sample(BATCH_SIZE)\n",
    "            sample = [sample_rearrange(x, device) for x in sample]\n",
    "            # Update Actors and Critics\n",
    "            for agent_idx in range(env.max_num_agents):\n",
    "                maddpg.update(sample, agent_idx)\n",
    "            # Update Target Parameters\n",
    "            maddpg.update_all_targets_params()\n",
    "    # After every 100 rounds, use the evaluate function to evaluate the trained agents, get the reward list ep_returns, and add it to return_list.\n",
    "    if (episode + 1) % 100 == 0:\n",
    "        episodes_returns = evaluate(env.max_num_agents - 1, maddpg, num_episode=100)\n",
    "        return_list.append(episodes_returns)\n",
    "        print(f\"Episode: {episode + 1}, {episodes_returns}\")\n",
    "# Close the Environment\n",
    "env.close()\n",
    "return_array = np.array(return_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8882a3a6",
   "metadata": {},
   "source": [
    "10. Plot\n",
    "It's time to save and visualize our results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "5d72fc77",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1UAAAHWCAYAAACfRKOZAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAv9VJREFUeJzs3XdYFNfXwPHv7NI7KEUQQbBg711j79HYTbVFTTHdJL9Ujaa9qSamaprGkqgxmhh7Syyx1yiioqiI0ntfdub9Y5VIsFAWlnI+z8MDOzN758zuBebsbYqmaRpCCCGEEEIIIUpEZ+kAhBBCCCGEEKIyk6RKCCGEEEIIIUpBkiohhBBCCCGEKAVJqoQQQgghhBCiFCSpEkIIIYQQQohSkKRKCCGEEEIIIUpBkiohhBBCCCGEKAVJqoQQQgghhBCiFCSpEkIIIYQQQohSkKRKCCGExV24cAFFUViwYEG5nrdHjx706NGjXM+Zl5fHiy++iL+/PzqdjmHDhpXr+cvDggULUBSFgwcPWjoUIYQoF5JUCSGqvOs3eNe/rKys8PPzY8KECURFRZWozNDQUN544w0uXLhg3mAriRtfz/9+Pfroo5YOr0L7/vvv+eCDDxg1ahQLFy7k2WeftXRIFdqLL76IoiiMHTvW0qHc1DvvvMPq1astHYYQwsKsLB2AEEKUl9mzZ1O3bl2ys7PZu3cvCxYsYNeuXZw4cQI7O7tilRUaGsqsWbPo0aMHgYGBZRNwBde3b1/GjRtXaHuDBg2KXVZAQABZWVlYW1ubI7QKbdu2bfj5+TFnzhxLh1LhaZrGTz/9RGBgIGvWrCEtLQ1nZ2dLh1XAO++8w6hRo6pki6MQougkqRJCVBsDBw6kbdu2AEyePJmaNWvy3nvv8fvvvzNmzBgLR2eSkZGBo6OjpcMokgYNGvDggw+apSxFUYqd2FZWsbGxuLm5ma08VVXJzc2tkq/fn3/+yeXLl9m2bRv9+/fn119/Zfz48ZYOSwghCpHuf0KIaqtbt24AnDt3rsD2sLAwRo0ahYeHB3Z2drRt25bff/89f/+CBQsYPXo0AD179szv9vbnn38CpgThjTfeKHS+wMBAJkyYUKAcRVH466+/ePzxx/Hy8qJ27dqAaaxP06ZNCQ0NpWfPnjg4OODn58f7779/x+tq2rQpPXv2LLRdVVX8/PwYNWpU/raff/6ZNm3a4OzsjIuLC82aNePTTz+94zmK6vp1HDp0iM6dO2Nvb0/dunX5+uuvCxx3szFV0dHRTJw4kdq1a2Nra0utWrW45557CnW5/PLLL2nSpAm2trb4+voybdo0kpOTC8Uyf/58goODsbe3p3379uzcufOmMefk5DBz5kzq1auHra0t/v7+vPjii+Tk5BQ4bvPmzXTt2hU3NzecnJxo2LAhr7zyyi1fi+vXuH37dk6ePFmo3mRkZDB9+nT8/f2xtbWlYcOGfPjhh2iaVqAcRVF44oknWLJkSf51b9iw4ZbnBVi/fj3dunXD0dERZ2dnBg8ezMmTJwscc/z4cSZMmEBQUBB2dnb4+PgwadIkEhISCpUXFRXFww8/jK+vL7a2ttStW5fHHnuM3NzcQq/lc889h6enJ46OjgwfPpy4uLjbxnqjJUuW0LhxY3r27EmfPn1YsmTJTY+7ePEiQ4cOxdHRES8vL5599lk2btxY4PW9bt++fQwYMABXV1ccHBzo3r07u3fvLnDMG2+8gaIohIeHM2HCBNzc3HB1dWXixIlkZmbmH6coChkZGSxcuDD//bzxd1wIUX1IS5UQotq6fnPu7u6ev+3kyZN06dIFPz8/XnrpJRwdHVm+fDnDhg1j5cqVDB8+nLvuuounnnqKuXPn8sorr9CoUSOA/O/F9fjjj+Pp6cmMGTPIyMjI356UlMSAAQMYMWIEY8aM4ZdffuF///sfzZo1Y+DAgbcsb+zYsbzxxhtER0fj4+OTv33Xrl1cuXKFe++9FzAlBffddx+9e/fmvffeA+DUqVPs3r2bp59++o5xZ2dnEx8fX2i7i4sLNjY2Ba5j0KBBjBkzhvvuu4/ly5fz2GOPYWNjw6RJk25Z/siRIzl58iRPPvkkgYGBxMbGsnnzZi5dupTf5fKNN95g1qxZ9OnTh8cee4zTp0/z1VdfceDAAXbv3p3fnfC7777jkUceoXPnzjzzzDOcP3+eoUOH4uHhgb+/f/45VVVl6NCh7Nq1i6lTp9KoUSP++ecf5syZw5kzZ/LHzpw8eZK7776b5s2bM3v2bGxtbQkPDy90c34jT09PFi1axNtvv016ejrvvvsuYKo3mqYxdOhQtm/fzsMPP0zLli3ZuHEjL7zwAlFRUYW6Cm7bto3ly5fzxBNPULNmzdt2QV20aBHjx4+nf//+vPfee2RmZvLVV1/RtWtXjhw5kv/czZs3c/78eSZOnIiPjw8nT55k/vz5nDx5kr1796IoCgBXrlyhffv2JCcnM3XqVEJCQoiKiuKXX34hMzOzwHv/5JNP4u7uzsyZM7lw4QKffPIJTzzxBMuWLbtlvNfl5OSwcuVKpk+fDsB9993HxIkTC9XrjIwMevXqxdWrV3n66afx8fFh6dKlbN++vVCZ27ZtY+DAgbRp04aZM2ei0+n44Ycf6NWrFzt37qR9+/YFjh8zZgx169bl3Xff5fDhw3z77bd4eXnl/74sWrSIyZMn0759e6ZOnQpAcHDwHa9NCFEFaUIIUcX98MMPGqBt2bJFi4uL0yIjI7VffvlF8/T01GxtbbXIyMj8Y3v37q01a9ZMy87Ozt+mqqrWuXNnrX79+vnbVqxYoQHa9u3bC50P0GbOnFloe0BAgDZ+/PhCcXXt2lXLy8srcGz37t01QPvxxx/zt+Xk5Gg+Pj7ayJEjb3u9p0+f1gDts88+K7D98ccf15ycnLTMzExN0zTt6aef1lxcXAqduyiAW3799NNPha7jo48+KnAdLVu21Ly8vLTc3FxN0zQtIiJCA7QffvhB0zRNS0pK0gDtgw8+uGUMsbGxmo2NjdavXz/NaDTmb//88881QPv+++81TdO03NxczcvLS2vZsqWWk5OTf9z8+fM1QOvevXv+tkWLFmk6nU7buXNngXN9/fXXGqDt3r1b0zRNmzNnjgZocXFxxXzlTK9JkyZNCmxbvXq1BmhvvfVWge2jRo3SFEXRwsPD87cBmk6n006ePHnHc6WlpWlubm7alClTCmyPjo7WXF1dC2y/Xi9u9NNPP2mAtmPHjvxt48aN03Q6nXbgwIFCx6uqqmnav3W7T58++ds0TdOeffZZTa/Xa8nJyXeM/ZdfftEA7ezZs5qmaVpqaqpmZ2enzZkzp8BxH330kQZoq1evzt+WlZWlhYSEFPgdVVVVq1+/vta/f/8CMWVmZmp169bV+vbtm79t5syZGqBNmjSpwLmGDx+u1ahRo8A2R0fHAr/XQojqSbr/CSGqjT59+uDp6Ym/vz+jRo3C0dGR33//Pb/LXWJiItu2bWPMmDGkpaURHx9PfHw8CQkJ9O/fn7Nnz5Z4tsDbmTJlCnq9vtB2JyenAmOWbGxsaN++PefPn79teQ0aNKBly5YFWgOMRiO//PILQ4YMwd7eHgA3NzcyMjLYvHlzieK+55572Lx5c6Gv/3Y9tLKy4pFHHilwHY888gixsbEcOnTopmXb29tjY2PDn3/+SVJS0k2P2bJlC7m5uTzzzDPodP/+O5syZQouLi6sXbsWgIMHDxIbG8ujjz5aoBVlwoQJuLq6FihzxYoVNGrUiJCQkPz3Pz4+nl69egHkt35cHxP122+/oapqUV6u21q3bh16vZ6nnnqqwPbp06ejaRrr168vsL179+40btz4juVu3ryZ5ORk7rvvvgLXo9fr6dChQ4HWnOv1Av5thezYsSMAhw8fBkwteatXr2bIkCH54xNvdL0167qpU6cW2NatWzeMRiMXL168Y+xLliyhbdu21KtXDyC/2+J/uwBu2LABPz8/hg4dmr/Nzs6OKVOmFDju6NGjnD17lvvvv5+EhIT81yIjI4PevXuzY8eOQu/lf2ey7NatGwkJCaSmpt4xfiFE9SLd/4QQ1cYXX3xBgwYNSElJ4fvvv2fHjh3Y2trm7w8PD0fTNF5//XVef/31m5YRGxuLn5+fWeOqW7fuTbfXrl270E2qu7s7x48fv2OZY8eO5ZVXXiEqKgo/Pz/+/PNPYmNjC0xL/fjjj7N8+XIGDhyIn58f/fr1Y8yYMQwYMKBIcdeuXZs+ffrc8ThfX99Ck29cnyHwwoUL+TfuN7K1teW9995j+vTpeHt707FjR+6++27GjRuX3/Xr+o15w4YNCzzXxsaGoKCg/P3Xv9evX7/AcdbW1gQFBRXYdvbsWU6dOoWnp+dNryU2NhYwvb7ffvstkydP5qWXXqJ3796MGDGCUaNGFUjwiurixYv4+voWmtnuepfS/yYht6oz/3X27FmA/KTwv1xcXPJ/TkxMZNasWfz888/513ldSkoKAHFxcaSmptK0adMinb9OnToFHl/vanurRPm65ORk1q1bxxNPPEF4eHj+9i5durBy5UrOnDmTX4cuXrxIcHBwod+V68nYdddfi9tNdJGSklKgO/Dt4r/xtRNCCEmqhBDVRvv27fM/XR82bBhdu3bl/vvv5/Tp0zg5OeV/Sv3888/Tv3//m5bx3xu14jAajTfdfmMLwY1u1noFFJq44GbGjh3Lyy+/zIoVK3jmmWdYvnw5rq6uBRImLy8vjh49ysaNG1m/fj3r16/nhx9+YNy4cSxcuLAIV1S2nnnmGYYMGcLq1avZuHEjr7/+Ou+++y7btm2jVatWZXJOVVVp1qwZH3/88U33Xx9/ZW9vz44dO9i+fTtr165lw4YNLFu2jF69erFp06Zbvnfmcqs681/X6/SiRYsKjEO6zsrq39uAMWPG8Pfff/PCCy/QsmXL/N+JAQMGlLg1rqR1eMWKFeTk5PDRRx/x0UcfFdq/ZMkSZs2aVaxYrl/DBx98QMuWLW96jJOTU4HHpfkdFEJUL5JUCSGqJb1ez7vvvkvPnj35/PPPeemll/JbLaytre/YAvPfT8Vv5O7uXmj2udzcXK5evVrquIuqbt26tG/fnmXLlvHEE0/w66+/MmzYsAItc2Bq1RkyZAhDhgxBVVUef/xx5s2bx+uvv16qBPJGV65cKTRV/JkzZwDuuMZXcHAw06dPZ/r06Zw9e5aWLVvy0UcfsXjxYgICAgA4ffp0gRan3NxcIiIi8t/D68edPXu2QIuNwWAgIiKCFi1aFDjfsWPH6N27923fYwCdTkfv3r3p3bs3H3/8Me+88w6vvvoq27dvL1IL3o0CAgLYsmVLoXWYwsLCClxDcV2fNMHLy+u2MSUlJbF161ZmzZrFjBkz8rdfb925ztPTExcXF06cOFGieIpqyZIlNG3alJkzZxbaN2/ePJYuXZqfVAUEBBAaGoqmaQXesxtbuODf18LFxaXY78/t3KmeCCGqBxlTJYSotnr06EH79u355JNPyM7OxsvLix49ejBv3rybJkA3TgV9PUG42dTdwcHB7Nixo8C2+fPn37KlqqyMHTuWvXv38v333xMfH1+g6x9QaKpsnU5H8+bNAQpNH14aeXl5zJs3L/9xbm4u8+bNw9PTkzZt2tz0OZmZmWRnZxfYFhwcjLOzc35sffr0wcbGhrlz5xZoOfjuu+9ISUlh8ODBALRt2xZPT0++/vrrAlN+L1iwoND7N2bMGKKiovjmm28KxZSVlZU/O2NiYmKh/ddbP0ry2g0aNAij0cjnn39eYPucOXNQFOW2sz3eTv/+/XFxceGdd97BYDAU2n+9Tl9vkflvC8wnn3xS4LFOp2PYsGGsWbOGgwcPFirPHC04kZGR7NixgzFjxjBq1KhCXxMnTiQ8PJx9+/blX2NUVFSBZQ+ys7MLvYdt2rQhODiYDz/8kPT09ELnLc5U7zdydHS86d8BIUT1Ii1VQohq7YUXXmD06NEsWLCARx99lC+++IKuXbvSrFkzpkyZQlBQEDExMezZs4fLly9z7NgxwHQDrdfree+990hJScHW1pZevXrh5eXF5MmTefTRRxk5ciR9+/bl2LFjbNy4kZo1a5brtY0ZM4bnn3+e559/Hg8Pj0Kfzk+ePJnExER69epF7dq1uXjxIp999hktW7Ys0vTwZ86cYfHixYW2e3t707dv3/zHvr6+vPfee1y4cIEGDRqwbNkyjh49yvz58/OnPL9Z2b1792bMmDE0btwYKysrVq1aRUxMTP6U8J6enrz88svMmjWLAQMGMHToUE6fPs2XX35Ju3bt8if5sLa25q233uKRRx6hV69ejB07loiICH744YdCY6oeeughli9fzqOPPsr27dvp0qULRqORsLAwli9fzsaNG2nbti2zZ89mx44dDB48mICAAGJjY/nyyy+pXbs2Xbt2veNr919DhgyhZ8+evPrqq1y4cIEWLVqwadMmfvvtN5555pkST9Pt4uLCV199xUMPPUTr1q2599578fT05NKlS6xdu5YuXbrw+eef4+Liwl133cX777+PwWDAz8+PTZs2ERERUajMd955h02bNtG9e/f8aeevXr3KihUr2LVrV6kXNl66dGn+FPM3M2jQIKysrFiyZAkdOnTgkUce4fPPP+e+++7j6aefplatWixZsiR/MeTrLUk6nY5vv/2WgQMH0qRJEyZOnIifnx9RUVFs374dFxcX1qxZU+x427Rpw5YtW/j444/x9fWlbt26dOjQoeQvgBCicrLUtINCCFFerk/vfLMpoI1GoxYcHKwFBwfnTy1+7tw5bdy4cZqPj49mbW2t+fn5aXfffbf2yy+/FHjuN998owUFBWl6vb7A1M1Go1H73//+p9WsWVNzcHDQ+vfvr4WHh99ySvWbxXWzabc1TdPGjx+vBQQEFPnau3TpogHa5MmTC+375ZdftH79+mleXl6ajY2NVqdOHe2RRx7Rrl69esdyuc2U6jdOUX79Og4ePKh16tRJs7Oz0wICArTPP/+8QHn/nVI9Pj5emzZtmhYSEqI5Ojpqrq6uWocOHbTly5cXiuXzzz/XQkJCNGtra83b21t77LHHtKSkpELHffnll1rdunU1W1tbrW3bttqOHTu07t27F4hX00xTsL/33ntakyZNNFtbW83d3V1r06aNNmvWLC0lJUXTNE3bunWrds8992i+vr6ajY2N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RbKR+vIGgNiwYYM8pqqqSvzpT38Sfn5+wtPTU4wdO1ZcunTJ4jpnzpwRI0eOFB4eHiIgIEDMnj1bGAwGizHffPON6Nu3r1CpVKJTp04W9yDn9PTTT4uIiAihUqlEYGCgGDp0qFxQCcHcoeb7bVHFHKKGPP744yIkJESoVCrRoUMH8fjjj4uTJ0/K510xdyQhhLDPHBkREREREZHz4zNVREREREREVmBRRUREREREZAUWVURERERERFZgUUVERERERGQFFlVERERERERWYFFFRERERERkBRZVREREREREVmBRRUREREREZAUWVURE5PLOnDkDSZKQlZVls3tMnjwZY8aMsdn1iYjIcbGoIiIihzd58mRIknTL64EHHmjS58PDw3Hp0iX06tXLxpESEdGdyN3eARARETXFAw88gA0bNlgcU6vVTfqsm5sbdDqdLcIiIiLiTBURETkHtVoNnU5n8fLz8wMASJKENWvWYOTIkfDw8ECnTp2wefNm+bO/Xf5XXFyMpKQkBAYGwsPDA126dLEo2H766ScMGTIEHh4e8Pf3x9SpU1FRUSGfNxqNmDVrFrRaLfz9/TFnzhwIISziNZlMWLJkCaKiouDh4YE+ffpYxNRYDERE5DxYVBERkUv4y1/+gnHjxiE7OxtJSUl44okncPz48QbH5uTk4Ouvv8bx48exZs0aBAQEAACuX7+OxMRE+Pn5ISMjA59++in++9//4vnnn5c/v2LFCrz//vtYv3499u3bh2vXruHzzz+3uMeSJUvwwQcf4O9//zuOHTuG5ORkPPnkk9i7d2+jMRARkXORxG//aY2IiMjBTJ48GR9++CE0Go3F8ZdeegkvvfQSJEnCtGnTsGbNGvncgAEDEBcXh7/97W84c+YMoqKicPjwYfTt2xcPP/wwAgICsH79+lvutW7dOsydOxfnzp1Du3btAADbtm3D6NGjcfHiRQQHByM0NBTJycl48cUXAQC1tbWIiopCfHw8tm7dCr1ej/bt2+O///0vEhIS5Gs/88wzqKysxKZNm24bAxERORc+U0VERE7h/vvvtyiaAKB9+/byn28uXszvG+r299xzz2HcuHH48ccfMWLECIwZMwb33nsvAOD48ePo06ePXFABwMCBA2EymZCbmwuNRoNLly6hf//+8nl3d3f069dPXgJ48uRJVFZWYvjw4Rb3rampQWxsbKMxEBGRc2FRRURETqFdu3bo3Llzq1xr5MiROHv2LLZt24a0tDQMHToU06dPxxtvvNEq1zc/f/XVV1+hQ4cOFufMzTVsHQMREbUdPlNFREQu4eDBg7e87969e4PjAwMDMWnSJHz44Yd46623sHbtWgBA9+7dkZ2djevXr8tjv//+eygUCkRHR8PX1xchISFIT0+Xz9fW1iIzM1N+36NHD6jVauTn56Nz584Wr/Dw8EZjICIi58KZKiIicgp6vR4FBQUWx9zd3eXmDp9++in69euH++67Dxs3bsQPP/yA9957r95rpaSkID4+Hj179oRer8eXX34pF2BJSUlYuHAhJk2ahEWLFuHy5cv485//jIkTJyI4OBgA8MILL2Dp0qXo0qULunXrhpUrV6KkpES+vre3N/7v//4PycnJMJlMuO+++1BaWorvv/8ePj4+mDRp0m1jICIi58KiioiInML27dsREhJicSw6Oho///wzAGDx4sVITU3Fn/70J4SEhOCjjz5Cjx496r2WSqXC/PnzcebMGXh4eGDQoEFITU0FAHh6emLHjh144YUXcPfdd8PT0xPjxo3DypUr5c/Pnj0bly5dwqRJk6BQKPD0009j7NixKC0tlcf89a9/RWBgIJYsWYJTp05Bq9UiLi4OL730UqMxEBGRc2H3PyIicnqSJOHzzz/HmDFj7B0KERHdgfhMFRERERERkRVYVBEREREREVmBz1QREZHT40p2IiKyJ85UERERERERWYFFFRERERERkRVYVBEREREREVmBRRUREREREZEVWFQRERERERFZgUUVERERERGRFVhUERERERERWYFFFRERERERkRX+P9tjpY8g+DZXAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "num_agents = return_array.shape[1]\n",
    "df = pd.DataFrame(return_array, columns=[f'agent_{i - 1}' if i > 0 else 'adversary_0' for i in range(num_agents)])\n",
    "df.to_excel('return_data.xlsx', index=False)\n",
    "\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.xlabel('Episodes')\n",
    "plt.ylabel('Return')\n",
    "plt.title('Return vs Episodes for each Agent')\n",
    "plt.grid(True)\n",
    "\n",
    "for agent in range(num_agents):\n",
    "    agent_returns = return_array[:, agent]\n",
    "    if agent == 0:\n",
    "        plt.plot(range(100, len(agent_returns) * 100 + 100, 100), return_array[:, 0], label=f'adversary_0')\n",
    "    else:\n",
    "        plt.plot(range(100, len(agent_returns) * 100 + 100, 100), agent_returns, label=f'agent_{agent - 1}')\n",
    "\n",
    "plt.legend()\n",
    "plt.savefig('return_plot.png')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
